update shapelib to 1.6.0 (#1257)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Thu, 25 Jan 2024 16:14:44 +0000 (09:14 -0700)
committerGitHub <noreply@github.com>
Thu, 25 Jan 2024 16:14:44 +0000 (09:14 -0700)
shapelib/COPYING [deleted file]
shapelib/LICENSE-LGPL [new file with mode: 0644]
shapelib/LICENSE-MIT [new file with mode: 0644]
shapelib/README.GPSBabel
shapelib/dbf_api.html
shapelib/dbfopen.c
shapelib/safileio.c
shapelib/shapefil.h
shapelib/shapelib.html
shapelib/shp_api.html
shapelib/shpopen.c

diff --git a/shapelib/COPYING b/shapelib/COPYING
deleted file mode 100644 (file)
index 0b643ac..0000000
+++ /dev/null
@@ -1,483 +0,0 @@
-
-                 GNU LIBRARY GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
-                    675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-\f
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-\f
-                 GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-\f
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-\f
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                           NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-     Appendix: How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
diff --git a/shapelib/LICENSE-LGPL b/shapelib/LICENSE-LGPL
new file mode 100644 (file)
index 0000000..12735e6
--- /dev/null
@@ -0,0 +1,481 @@
+                  GNU LIBRARY GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+                  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/shapelib/LICENSE-MIT b/shapelib/LICENSE-MIT
new file mode 100644 (file)
index 0000000..34fb342
--- /dev/null
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 1999, Frank Warmerdam
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
index a3f95350970444612e3f8a70ae0e3b0fc58ed77d..f5bba78a8b0672b089ca6df5183a544e76b7aa77 100644 (file)
@@ -1,4 +1,4 @@
-This is a subset of Shapelib v1.5.0 from http://shapelib.maptools.org/
+This is a subset of Shapelib v1.6.0 from http://shapelib.maptools.org/
 
 The source is unmodified.  It's subsetted here only to reduce 
 the amount of size in our tree that it takes and to reduce ongoing 
index 0bd0da1b84decb32de162adc192a1858949fb5e5..cdd29a22fd6d13ce26872f3f2c248b7337631d11 100644 (file)
@@ -22,13 +22,13 @@ DBFHandle DBFOpen( const char * pszDBFFile, const char * pszAccess );
   pszDBFFile:          The name of the xBase (.dbf) file to access.
 
   pszAccess:           The fopen() style access string.  At this time only
-                       "rb" (read-only binary) and "rb+" (read/write binary) 
+                       "rb" (read-only binary) and "rb+" (read/write binary)
                        should be used.
 </pre>
 
   The DBFOpen() function should be used to establish access to an existing
-  xBase format table file.  The returned DBFHandle is passed to other 
-  access functions, and DBFClose() should be invoked to recover resources, and 
+  xBase format table file.  The returned DBFHandle is passed to other
+  access functions, and DBFClose() should be invoked to recover resources, and
   flush changes to disk when complete.  The DBFCreate() function should
   called to create new xBase files.  As a convenience, DBFOpen() can be
   called with the name of a .shp or .shx file, and it will figure out the
@@ -43,8 +43,8 @@ DBFHandle DBFCreate( const char * pszDBFFile );
 
   pszDBFFile:          The name of the xBase (.dbf) file to create.
 </pre>
-  
-  The DBFCreate() function creates a new xBase format file with the given 
+
+  The DBFCreate() function creates a new xBase format file with the given
   name, and returns an access handle that can be used with other DBF functions.
   The newly created file will have no fields, and no records.  Fields should
   be added with DBFAddField() before any records add written.
@@ -105,19 +105,19 @@ DBFFieldType DBFGetFieldInfo( DBFHandle hDBF, int iField, char * pszFieldName,
   hDBF:                The access handle for the file to be queried, as returned by
                DBFOpen(), or DBFCreate().
 
-  iField:      The field to be queried.  This should be a number between 
+  iField:      The field to be queried.  This should be a number between
                 0 and n-1, where n is the number fields on the file, as
                 returned by DBFGetFieldCount().
 
   pszFieldName:        If this pointer is not NULL the name of the requested field
-               will be written to this location.  The pszFieldName buffer 
+               will be written to this location.  The pszFieldName buffer
                 should be at least 12 character is size in order to hold
-               the longest possible field name of 11 characters plus a 
+               the longest possible field name of 11 characters plus a
                 terminating zero character.
 
   pnWidth:     If this pointer is not NULL, the width of the requested field
                will be returned in the int pointed to by pnWidth.  This is
-                the width in characters.  
+                the width in characters.
 
   pnDecimals:  If this pointer is not NULL, the number of decimal places
                 precision defined for the field will be returned.  This is
@@ -145,7 +145,7 @@ DBFFieldType DBFGetFieldInfo( DBFHandle hDBF, int iField, char * pszFieldName,
 <h2>DBFAddField()</h2>
 
 <pre>
-int DBFAddField( DBFHandle hDBF, const char * pszFieldName, 
+int DBFAddField( DBFHandle hDBF, const char * pszFieldName,
                  DBFFieldType eType, int nWidth, int nDecimals );
 
   hDBF:                The access handle for the file to be updated, as returned by
@@ -186,7 +186,7 @@ int DBFAddField( DBFHandle hDBF, const char * pszFieldName,
 
 <pre>
 int DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-  
+
   hDBF:                The access handle for the file to be queried, as returned by
                DBFOpen(), or DBFCreate().
 
@@ -206,7 +206,7 @@ int DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
 
 <pre>
 double DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
-  
+
   hDBF:                The access handle for the file to be queried, as returned by
                DBFOpen(), or DBFCreate().
 
@@ -226,7 +226,7 @@ double DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
 
 <pre>
 const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
-  
+
   hDBF:                The access handle for the file to be queried, as returned by
                DBFOpen(), or DBFCreate().
 
@@ -237,10 +237,10 @@ const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
 </pre>
 
   The DBFReadStringAttribute() will read the value of one field and return
-  it as a string.  This function may be used on any field type (including 
+  it as a string.  This function may be used on any field type (including
   FTInteger and FTDouble) and will return the string representation stored
   in the .dbf file.  The returned pointer is to an internal buffer
-  which is only valid untill the next DBF function call.  It's contents may
+  which is only valid until the next DBF function call.  It's contents may
   be copied with normal string functions such as strcpy(), or strdup().  If
   the TRIM_DBF_WHITESPACE macro is defined in shapefil.h (it is by default)
   then all leading and trailing space (ASCII 32) characters will be stripped
@@ -252,7 +252,7 @@ const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
 
 <pre>
 int DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
-  
+
   hDBF:                The access handle for the file to be queried, as returned by
                DBFOpen(), or DBFCreate().
 
@@ -265,7 +265,7 @@ int DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
   This function will return TRUE if the indicated field is NULL valued
   otherwise FALSE.  Note that NULL fields are represented in the .dbf file
   as having all spaces in the field.  Reading NULL fields will result in
-  a value of 0.0 or an empty string with the other DBFRead*Attribute() 
+  a value of 0.0 or an empty string with the other DBFRead*Attribute()
   functions.<p>
 
 <!-------------------------------------------------------------------------->
@@ -289,7 +289,7 @@ int DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
 
 The DBFWriteIntegerAttribute() function is used to write a value to a numeric
 field (FTInteger, or FTDouble).  If the write succeeds the value TRUE will
-be returned, otherwise FALSE will be returned.  If the value is too large to 
+be returned, otherwise FALSE will be returned.  If the value is too large to
 fit in the field, it will be truncated and FALSE returned.<p>
 
 <!-------------------------------------------------------------------------->
@@ -313,7 +313,7 @@ int DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
 
 The DBFWriteDoubleAttribute() function is used to write a value to a numeric
 field (FTInteger, or FTDouble).  If the write succeeds the value TRUE will
-be returned, otherwise FALSE will be returned.  If the value is too large to 
+be returned, otherwise FALSE will be returned.  If the value is too large to
 fit in the field, it will be truncated and FALSE returned.<p>
 
 <!-------------------------------------------------------------------------->
@@ -336,8 +336,8 @@ int DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
 </pre>
 
 The DBFWriteStringAttribute() function is used to write a value to a string
-field (FString).  If the write succeeds the value TRUE willbe returned, 
-otherwise FALSE will be returned.  If the value is too large to 
+field (FString).  If the write succeeds the value TRUE willbe returned,
+otherwise FALSE will be returned.  If the value is too large to
 fit in the field, it will be truncated and FALSE returned.<p>
 
 <!-------------------------------------------------------------------------->
@@ -358,7 +358,7 @@ int DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
 
 The DBFWriteNULLAttribute() function is used to clear the indicated field
 to a NULL value.  In the .dbf file this is represented by setting the entire
-field to spaces.  If the write succeeds the value TRUE willbe returned, 
+field to spaces.  If the write succeeds the value TRUE willbe returned,
 otherwise FALSE will be returned.<p>
 
 <!-------------------------------------------------------------------------->
@@ -414,7 +414,7 @@ char DBFGetNativeFieldType( DBFHandle hDBF, int iField );
 
   hDBF:                The access handle for the file.
   iField:       The field index to query.
-  
+
 </pre>
 
   This function returns the DBF type code of the indicated field. It will
index 218db70cf0ee815cfb453c5c9f0607b23635324b..ee5be97f0c0897aaf23d7ea9485fa770b2a1f678 100644 (file)
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dbfopen.c,v 1.94 2018-08-16 15:39:07 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of .dbf access API documented in dbf_api.html.
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2019, Even Rouault <even dot rouault at spatialys.com>
  *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING).  This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- *
- * $Log: dbfopen.c,v $
- * Revision 1.94  2018-08-16 15:39:07  erouault
- * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
- * internal shapelib. Mostly to allow building those files as C++
- * without warning. Also add FTDate entry in DBFFieldType
- * (see https://github.com/OSGeo/gdal/pull/308). And some other
- * code cleanups
- *
- * Revision 1.93  2018-08-16 15:24:46  erouault
- * * dbfopen.c: fix a bug where the end of file character was
- * written on top of the first character of the first field name
- * when deleting a field on a .dbf without records.
- * Fixes https://github.com/OSGeo/gdal/issues/863
- *
- * Revision 1.92  2016-12-05 18:44:08  erouault
- * * dbfopen.c, shapefil.h: write DBF end-of-file character 0x1A by default.
- * This behaviour can be controlled with the DBFSetWriteEndOfFileChar()
- * function.
- *
- * Revision 1.91  2016-12-05 12:44:05  erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.90  2016-12-04 15:30:15  erouault
- * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
- * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
- * structures extended with new members. New functions:
- * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
- * SHPSetFastModeReadObject
- *
- * * sbnsearch.c: new file to implement original ESRI .sbn spatial
- * index reading. (no write support). New functions:
- * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
- * SBNSearchDiskTreeInteger, SBNSearchFreeIds
- *
- * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
- * with new file and symbols.
- *
- * * commit: helper script to cvs commit
- *
- * Revision 1.89  2011-07-24 05:59:25  fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.88  2011-05-13 17:35:17  fwarmerdam
- * added DBFReorderFields() and DBFAlterFields() functions (from Even)
- *
- * Revision 1.87  2011-05-07 22:41:02  fwarmerdam
- * ensure pending record is flushed when adding a native field (GDAL #4073)
- *
- * Revision 1.86  2011-04-17 15:15:29  fwarmerdam
- * Removed unused variable.
- *
- * Revision 1.85  2010-12-06 16:09:34  fwarmerdam
- * fix buffer read overrun fetching code page (bug 2276)
- *
- * Revision 1.84  2009-10-29 19:59:48  fwarmerdam
- * avoid crash on truncated header (gdal #3093)
- *
- * Revision 1.83  2008/11/12 14:28:15  fwarmerdam
- * DBFCreateField() now works on files with records
- *
- * Revision 1.82  2008/11/11 17:47:09  fwarmerdam
- * added DBFDeleteField() function
- *
- * Revision 1.81  2008/01/03 17:48:13  bram
- * in DBFCreate, use default code page LDID/87 (= 0x57, ANSI)
- * instead of LDID/3.  This seems to be the same as what ESRI
- * would be doing by default.
- *
- * Revision 1.80  2007/12/30 14:36:39  fwarmerdam
- * avoid syntax issue with last comment.
- *
- * Revision 1.79  2007/12/30 14:35:48  fwarmerdam
- * Avoid char* / unsigned char* warnings.
- *
- * Revision 1.78  2007/12/18 18:28:07  bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.77  2007/12/15 20:25:21  bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function.  This is
- * either the number from the LDID header field ("LDID/<number>") or as the
- * content of an accompanying .CPG file.  When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.76  2007/12/12 22:21:32  bram
- * DBFClose: check for NULL psDBF handle before trying to close it.
- *
- * Revision 1.75  2007/12/06 13:58:19  fwarmerdam
- * make sure file offset calculations are done in as SAOffset
- *
- * Revision 1.74  2007/12/06 07:00:25  fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.73  2007/09/03 19:48:11  fwarmerdam
- * move DBFReadAttribute() static dDoubleField into dbfinfo
- *
- * Revision 1.72  2007/09/03 19:34:06  fwarmerdam
- * Avoid use of static tuple buffer in DBFReadTuple()
- *
- * Revision 1.71  2006/06/22 14:37:18  fwarmerdam
- * avoid memory leak if dbfopen fread fails
- *
- * Revision 1.70  2006/06/17 17:47:05  fwarmerdam
- * use calloc() for dbfinfo in DBFCreate
- *
- * Revision 1.69  2006/06/17 15:34:32  fwarmerdam
- * disallow creating fields wider than 255
- *
- * Revision 1.68  2006/06/17 15:12:40  fwarmerdam
- * Fixed C++ style comments.
- *
- * Revision 1.67  2006/06/17 00:24:53  fwarmerdam
- * Don't treat non-zero decimals values as high order byte for length
- * for strings.  It causes serious corruption for some files.
- * http://bugzilla.remotesensing.org/show_bug.cgi?id=1202
- *
- * Revision 1.66  2006/03/29 18:26:20  fwarmerdam
- * fixed bug with size of pachfieldtype in dbfcloneempty
- *
- * Revision 1.65  2006/02/15 01:14:30  fwarmerdam
- * added DBFAddNativeFieldType
- *
- * Revision 1.64  2006/02/09 00:29:04  fwarmerdam
- * Changed to put spaces into string fields that are NULL as
- * per http://bugzilla.maptools.org/show_bug.cgi?id=316.
- *
- * Revision 1.63  2006/01/25 15:35:43  fwarmerdam
- * check success on DBFFlushRecord
- *
- * Revision 1.62  2006/01/10 16:28:03  fwarmerdam
- * Fixed typo in CPLError.
- *
- * Revision 1.61  2006/01/10 16:26:29  fwarmerdam
- * Push loading record buffer into DBFLoadRecord.
- * Implement CPL error reporting if USE_CPL defined.
- *
- * Revision 1.60  2006/01/05 01:27:27  fwarmerdam
- * added dbf deletion mark/fetch
- *
- * Revision 1.59  2005/03/14 15:20:28  fwarmerdam
- * Fixed last change.
- *
- * Revision 1.58  2005/03/14 15:18:54  fwarmerdam
- * Treat very wide fields with no decimals as double.  This is
- * more than 32bit integer fields.
- *
- * Revision 1.57  2005/02/10 20:16:54  fwarmerdam
- * Make the pszStringField buffer for DBFReadAttribute() static char [256]
- * as per bug 306.
- *
- * Revision 1.56  2005/02/10 20:07:56  fwarmerdam
- * Fixed bug 305 in DBFCloneEmpty() - header length problem.
- *
- * Revision 1.55  2004/09/26 20:23:46  fwarmerdam
- * avoid warnings with rcsid and signed/unsigned stuff
- *
- * Revision 1.54  2004/09/15 16:26:10  fwarmerdam
- * Treat all blank numeric fields as null too.
- */
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+ ******************************************************************************/
 
 #include "shapefil.h"
 
 #include <math.h>
+#include <stdbool.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
 #include "cpl_string.h"
 #else
 
-#if defined(WIN32) || defined(_WIN32)
-#    define STRCASECMP(a,b)         (stricmp(a,b))
-#  else
+#if defined(_MSC_VER)
+#define STRCASECMP(a, b) (_stricmp(a, b))
+#elif defined(WIN32) || defined(_WIN32)
+#define STRCASECMP(a, b) (stricmp(a, b))
+#else
 #include <strings.h>
-#    define STRCASECMP(a,b)         (strcasecmp(a,b))
+#define STRCASECMP(a, b) (strcasecmp(a, b))
 #endif
 
 #if defined(_MSC_VER)
-# if _MSC_VER < 1900
-#     define snprintf _snprintf
-# endif
+#if _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
 #elif defined(WIN32) || defined(_WIN32)
-#  ifndef snprintf
-#     define snprintf _snprintf
-#  endif
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
 #endif
 
 #define CPLsprintf sprintf
 #define CPLsnprintf snprintf
 #endif
 
-SHP_CVSID("$Id: dbfopen.c,v 1.94 2018-08-16 15:39:07 erouault Exp $")
-
 #ifndef FALSE
-#  define FALSE                0
-#  define TRUE         1
+#define FALSE 0
+#define TRUE 1
 #endif
 
 /* File header size */
-#define XBASE_FILEHDR_SZ         32
+#define XBASE_FILEHDR_SZ 32
 
 #define HEADER_RECORD_TERMINATOR 0x0D
 
 /* See http://www.manmrk.net/tutorials/database/xbase/dbf.html */
-#define END_OF_FILE_CHARACTER    0x1A
+#define END_OF_FILE_CHARACTER 0x1A
 
 #ifdef USE_CPL
-CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused)
+{
+}
 #else
 #define CPL_IGNORE_RET_VAL_INT(x) x
 #endif
 
 #ifdef __cplusplus
-#define STATIC_CAST(type,x) static_cast<type>(x)
-#define REINTERPRET_CAST(type,x) reinterpret_cast<type>(x)
-#define CONST_CAST(type,x) const_cast<type>(x)
+#define STATIC_CAST(type, x) static_cast<type>(x)
+#define REINTERPRET_CAST(type, x) reinterpret_cast<type>(x)
+#define CONST_CAST(type, x) const_cast<type>(x)
 #define SHPLIB_NULLPTR nullptr
 #else
-#define STATIC_CAST(type,x) ((type)(x))
-#define REINTERPRET_CAST(type,x) ((type)(x))
-#define CONST_CAST(type,x) ((type)(x))
+#define STATIC_CAST(type, x) ((type)(x))
+#define REINTERPRET_CAST(type, x) ((type)(x))
+#define CONST_CAST(type, x) ((type)(x))
 #define SHPLIB_NULLPTR NULL
 #endif
 
-/************************************************************************/
-/*                             SfRealloc()                              */
-/*                                                                      */
-/*      A realloc cover function that will access a NULL pointer as     */
-/*      a valid input.                                                  */
-/************************************************************************/
-
-static void * SfRealloc( void * pMem, int nNewSize )
-
-{
-    if( pMem == SHPLIB_NULLPTR )
-        return malloc(nNewSize);
-    else
-        return realloc(pMem,nNewSize);
-}
-
 /************************************************************************/
 /*                           DBFWriteHeader()                           */
 /*                                                                      */
@@ -288,19 +90,18 @@ static void * SfRealloc( void * pMem, int nNewSize )
 /************************************************************************/
 
 static void DBFWriteHeader(DBFHandle psDBF)
-
 {
-    unsigned char      abyHeader[XBASE_FILEHDR_SZ] = { 0 };
+    unsigned char abyHeader[XBASE_FILEHDR_SZ] = {0};
 
-    if( !psDBF->bNoHeader )
+    if (!psDBF->bNoHeader)
         return;
 
     psDBF->bNoHeader = FALSE;
 
-/* -------------------------------------------------------------------- */
-/*     Initialize the file header information.                         */
-/* -------------------------------------------------------------------- */
-    abyHeader[0] = 0x03;               /* memo field? - just copying   */
+    /* -------------------------------------------------------------------- */
+    /*      Initialize the file header information.                         */
+    /* -------------------------------------------------------------------- */
+    abyHeader[0] = 0x03; /* memo field? - just copying */
 
     /* write out update date */
     abyHeader[1] = STATIC_CAST(unsigned char, psDBF->nUpdateYearSince1900);
@@ -317,35 +118,33 @@ static void DBFWriteHeader(DBFHandle psDBF)
 
     abyHeader[29] = STATIC_CAST(unsigned char, psDBF->iLanguageDriver);
 
-/* -------------------------------------------------------------------- */
-/*      Write the initial 32 byte file header, and all the field        */
-/*      descriptions.                                                  */
-/* -------------------------------------------------------------------- */
-    psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
-    psDBF->sHooks.FWrite( abyHeader, XBASE_FILEHDR_SZ, 1, psDBF->fp );
-    psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
-                          psDBF->fp );
-
-/* -------------------------------------------------------------------- */
-/*      Write out the newline character if there is room for it.        */
-/* -------------------------------------------------------------------- */
-    if( psDBF->nHeaderLength > XBASE_FLDHDR_SZ*psDBF->nFields +
-                               XBASE_FLDHDR_SZ )
+    /* -------------------------------------------------------------------- */
+    /*      Write the initial 32 byte file header, and all the field        */
+    /*      descriptions.                                                   */
+    /* -------------------------------------------------------------------- */
+    psDBF->sHooks.FSeek(psDBF->fp, 0, 0);
+    psDBF->sHooks.FWrite(abyHeader, XBASE_FILEHDR_SZ, 1, psDBF->fp);
+    psDBF->sHooks.FWrite(psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
+                         psDBF->fp);
+
+    /* -------------------------------------------------------------------- */
+    /*      Write out the newline character if there is room for it.        */
+    /* -------------------------------------------------------------------- */
+    if (psDBF->nHeaderLength >
+        XBASE_FLDHDR_SZ * psDBF->nFields + XBASE_FLDHDR_SZ)
     {
-        char   cNewline;
-
-        cNewline = HEADER_RECORD_TERMINATOR;
-        psDBF->sHooks.FWrite( &cNewline, 1, 1, psDBF->fp );
+        char cNewline = HEADER_RECORD_TERMINATOR;
+        psDBF->sHooks.FWrite(&cNewline, 1, 1, psDBF->fp);
     }
 
-/* -------------------------------------------------------------------- */
-/*      If the file is new, add a EOF character.                        */
-/* -------------------------------------------------------------------- */
-    if( psDBF->nRecords == 0 && psDBF->bWriteEndOfFileChar )
+    /* -------------------------------------------------------------------- */
+    /*      If the file is new, add a EOF character.                        */
+    /* -------------------------------------------------------------------- */
+    if (psDBF->nRecords == 0 && psDBF->bWriteEndOfFileChar)
     {
         char ch = END_OF_FILE_CHARACTER;
 
-        psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+        psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
     }
 }
 
@@ -355,125 +154,149 @@ static void DBFWriteHeader(DBFHandle psDBF)
 /*      Write out the current record if there is one.                   */
 /************************************************************************/
 
-static int DBFFlushRecord( DBFHandle psDBF )
-
+static bool DBFFlushRecord(DBFHandle psDBF)
 {
-    SAOffset   nRecordOffset;
-
-    if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
+    if (psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1)
     {
-       psDBF->bCurrentRecordModified = FALSE;
-
-       nRecordOffset =
-            psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nCurrentRecord)
-            + psDBF->nHeaderLength;
+        psDBF->bCurrentRecordModified = FALSE;
+
+        const SAOffset nRecordOffset =
+            psDBF->nRecordLength *
+                STATIC_CAST(SAOffset, psDBF->nCurrentRecord) +
+            psDBF->nHeaderLength;
+
+        /* -------------------------------------------------------------------- */
+        /*      Guard FSeek with check for whether we're already at position;   */
+        /*      no-op FSeeks defeat network filesystems' write buffering.       */
+        /* -------------------------------------------------------------------- */
+        if (psDBF->bRequireNextWriteSeek ||
+            psDBF->sHooks.FTell(psDBF->fp) != nRecordOffset)
+        {
+            if (psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0) != 0)
+            {
+                char szMessage[128];
+                snprintf(
+                    szMessage, sizeof(szMessage),
+                    "Failure seeking to position before writing DBF record %d.",
+                    psDBF->nCurrentRecord);
+                psDBF->sHooks.Error(szMessage);
+                return false;
+            }
+        }
 
-       if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0
-            || psDBF->sHooks.FWrite( psDBF->pszCurrentRecord,
-                                     psDBF->nRecordLength,
-                                     1, psDBF->fp ) != 1 )
+        if (psDBF->sHooks.FWrite(psDBF->pszCurrentRecord, psDBF->nRecordLength,
+                                 1, psDBF->fp) != 1)
         {
             char szMessage[128];
-            snprintf( szMessage, sizeof(szMessage), "Failure writing DBF record %d.",
-                     psDBF->nCurrentRecord );
-            psDBF->sHooks.Error( szMessage );
-            return FALSE;
+            snprintf(szMessage, sizeof(szMessage),
+                     "Failure writing DBF record %d.", psDBF->nCurrentRecord);
+            psDBF->sHooks.Error(szMessage);
+            return false;
         }
 
-        if( psDBF->nCurrentRecord == psDBF->nRecords - 1 )
+        /* -------------------------------------------------------------------- */
+        /*      If next op is also a write, allow possible skipping of FSeek.   */
+        /* -------------------------------------------------------------------- */
+        psDBF->bRequireNextWriteSeek = FALSE;
+
+        if (psDBF->nCurrentRecord == psDBF->nRecords - 1)
         {
-            if( psDBF->bWriteEndOfFileChar )
+            if (psDBF->bWriteEndOfFileChar)
             {
                 char ch = END_OF_FILE_CHARACTER;
-                psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+                psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
             }
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           DBFLoadRecord()                            */
 /************************************************************************/
 
-static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
-
+static bool DBFLoadRecord(DBFHandle psDBF, int iRecord)
 {
-    if( psDBF->nCurrentRecord != iRecord )
+    if (psDBF->nCurrentRecord != iRecord)
     {
-        SAOffset nRecordOffset;
+        if (!DBFFlushRecord(psDBF))
+            return false;
 
-       if( !DBFFlushRecord( psDBF ) )
-            return FALSE;
-
-       nRecordOffset =
-            psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+        const SAOffset nRecordOffset =
+            psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+            psDBF->nHeaderLength;
 
-       if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
+        if (psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, SEEK_SET) != 0)
         {
             char szMessage[128];
-            snprintf( szMessage, sizeof(szMessage), "fseek(%ld) failed on DBF file.",
-                      STATIC_CAST(long, nRecordOffset) );
-            psDBF->sHooks.Error( szMessage );
-            return FALSE;
+            snprintf(szMessage, sizeof(szMessage),
+                     "fseek(%ld) failed on DBF file.",
+                     STATIC_CAST(long, nRecordOffset));
+            psDBF->sHooks.Error(szMessage);
+            return false;
         }
 
-       if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord,
-                                 psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
+        if (psDBF->sHooks.FRead(psDBF->pszCurrentRecord, psDBF->nRecordLength,
+                                1, psDBF->fp) != 1)
         {
             char szMessage[128];
-            snprintf( szMessage, sizeof(szMessage), "fread(%d) failed on DBF file.",
-                     psDBF->nRecordLength );
-            psDBF->sHooks.Error( szMessage );
-            return FALSE;
+            snprintf(szMessage, sizeof(szMessage),
+                     "fread(%d) failed on DBF file.", psDBF->nRecordLength);
+            psDBF->sHooks.Error(szMessage);
+            return false;
         }
 
-       psDBF->nCurrentRecord = iRecord;
+        psDBF->nCurrentRecord = iRecord;
+        /* -------------------------------------------------------------------- */
+        /*      Require a seek for next write in case of mixed R/W operations.  */
+        /* -------------------------------------------------------------------- */
+        psDBF->bRequireNextWriteSeek = TRUE;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                          DBFUpdateHeader()                           */
 /************************************************************************/
 
-void SHPAPI_CALL
-DBFUpdateHeader( DBFHandle psDBF )
-
+void SHPAPI_CALL DBFUpdateHeader(DBFHandle psDBF)
 {
-    unsigned char              abyFileHeader[XBASE_FILEHDR_SZ];
-
-    if( psDBF->bNoHeader )
-        DBFWriteHeader( psDBF );
+    if (psDBF->bNoHeader)
+        DBFWriteHeader(psDBF);
 
-    if( !DBFFlushRecord( psDBF ) )
+    if (!DBFFlushRecord(psDBF))
         return;
 
-    psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
-    psDBF->sHooks.FRead( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
+    psDBF->sHooks.FSeek(psDBF->fp, 0, 0);
+
+    unsigned char abyFileHeader[XBASE_FILEHDR_SZ] = {0};
+    psDBF->sHooks.FRead(abyFileHeader, 1, sizeof(abyFileHeader), psDBF->fp);
 
     abyFileHeader[1] = STATIC_CAST(unsigned char, psDBF->nUpdateYearSince1900);
     abyFileHeader[2] = STATIC_CAST(unsigned char, psDBF->nUpdateMonth);
     abyFileHeader[3] = STATIC_CAST(unsigned char, psDBF->nUpdateDay);
     abyFileHeader[4] = STATIC_CAST(unsigned char, psDBF->nRecords & 0xFF);
-    abyFileHeader[5] = STATIC_CAST(unsigned char, (psDBF->nRecords>>8) & 0xFF);
-    abyFileHeader[6] = STATIC_CAST(unsigned char, (psDBF->nRecords>>16) & 0xFF);
-    abyFileHeader[7] = STATIC_CAST(unsigned char, (psDBF->nRecords>>24) & 0xFF);
+    abyFileHeader[5] =
+        STATIC_CAST(unsigned char, (psDBF->nRecords >> 8) & 0xFF);
+    abyFileHeader[6] =
+        STATIC_CAST(unsigned char, (psDBF->nRecords >> 16) & 0xFF);
+    abyFileHeader[7] =
+        STATIC_CAST(unsigned char, (psDBF->nRecords >> 24) & 0xFF);
 
-    psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
-    psDBF->sHooks.FWrite( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
+    psDBF->sHooks.FSeek(psDBF->fp, 0, 0);
+    psDBF->sHooks.FWrite(abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp);
 
-    psDBF->sHooks.FFlush( psDBF->fp );
+    psDBF->sHooks.FFlush(psDBF->fp);
 }
 
 /************************************************************************/
 /*                       DBFSetLastModifiedDate()                       */
 /************************************************************************/
 
-void SHPAPI_CALL
-DBFSetLastModifiedDate( DBFHandle psDBF, int nYYSince1900, int nMM, int nDD )
+void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900,
+                                        int nMM, int nDD)
 {
     psDBF->nUpdateYearSince1900 = nYYSince1900;
     psDBF->nUpdateMonth = nMM;
@@ -486,30 +309,27 @@ DBFSetLastModifiedDate( DBFHandle psDBF, int nYYSince1900, int nMM, int nDD )
 /*      Open a .dbf file.                                               */
 /************************************************************************/
 
-DBFHandle SHPAPI_CALL
-DBFOpen( const char * pszFilename, const char * pszAccess )
+DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
 
 {
     SAHooks sHooks;
 
-    SASetupDefaultHooks( &sHooks );
+    SASetupDefaultHooks(&sHooks);
 
-    return DBFOpenLL( pszFilename, pszAccess, &sHooks );
+    return DBFOpenLL(pszFilename, pszAccess, &sHooks);
 }
 
 /************************************************************************/
 /*                      DBFGetLenWithoutExtension()                     */
 /************************************************************************/
 
-static int DBFGetLenWithoutExtension(const charpszBasename)
+static int DBFGetLenWithoutExtension(const char *pszBasename)
 {
-    int i;
-    int nLen = STATIC_CAST(int, strlen(pszBasename));
-    for( i = nLen-1;
-         i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\';
-         i-- )
+    const int nLen = STATIC_CAST(int, strlen(pszBasename));
+    for (int i = nLen - 1;
+         i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\'; i--)
     {
-        if( pszBasename[i] == '.' )
+        if (pszBasename[i] == '.')
         {
             return i;
         }
@@ -523,65 +343,58 @@ static int DBFGetLenWithoutExtension(const char* pszBasename)
 /*      Open a .dbf file.                                               */
 /************************************************************************/
 
-DBFHandle SHPAPI_CALL
-DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
-
+DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
+                                const SAHooks *psHooks)
 {
-    DBFHandle          psDBF;
-    SAFile             pfCPG;
-    unsigned char      *pabyBuf;
-    int                        nFields, nHeadLen, iField;
-    char               *pszFullname;
-    int                 nBufSize = 500;
-    int                 nLenWithoutExtension;
-
-/* -------------------------------------------------------------------- */
-/*      We only allow the access strings "rb" and "r+".                  */
-/* -------------------------------------------------------------------- */
-    if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
-        && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
-        && strcmp(pszAccess,"r+b") != 0 )
+    /* -------------------------------------------------------------------- */
+    /*      We only allow the access strings "rb" and "r+".                  */
+    /* -------------------------------------------------------------------- */
+    if (strcmp(pszAccess, "r") != 0 && strcmp(pszAccess, "r+") != 0 &&
+        strcmp(pszAccess, "rb") != 0 && strcmp(pszAccess, "rb+") != 0 &&
+        strcmp(pszAccess, "r+b") != 0)
         return SHPLIB_NULLPTR;
 
-    if( strcmp(pszAccess,"r") == 0 )
+    if (strcmp(pszAccess, "r") == 0)
         pszAccess = "rb";
 
-    if( strcmp(pszAccess,"r+") == 0 )
+    if (strcmp(pszAccess, "r+") == 0)
         pszAccess = "rb+";
 
-/* -------------------------------------------------------------------- */
-/*     Compute the base (layer) name.  If there is any extension       */
-/*     on the passed in filename we will strip it off.                 */
-/* -------------------------------------------------------------------- */
-    nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
-    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    /* -------------------------------------------------------------------- */
+    /*      Compute the base (layer) name.  If there is any extension       */
+    /*      on the passed in filename we will strip it off.                 */
+    /* -------------------------------------------------------------------- */
+    const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
+    char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
     memcpy(pszFullname, pszFilename, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
 
-    psDBF = STATIC_CAST(DBFHandle, calloc( 1, sizeof(DBFInfo) ));
-    psDBF->fp = psHooks->FOpen( pszFullname, pszAccess );
-    memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
+    DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
+    psDBF->fp = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
+    memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
 
-    if( psDBF->fp == SHPLIB_NULLPTR )
+    if (psDBF->fp == SHPLIB_NULLPTR)
     {
         memcpy(pszFullname + nLenWithoutExtension, ".DBF", 5);
-        psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess );
+        psDBF->fp =
+            psDBF->sHooks.FOpen(pszFullname, pszAccess, psHooks->pvUserData);
     }
 
     memcpy(pszFullname + nLenWithoutExtension, ".cpg", 5);
-    pfCPG = psHooks->FOpen( pszFullname, "r" );
-    if( pfCPG == SHPLIB_NULLPTR )
+    SAFile pfCPG = psHooks->FOpen(pszFullname, "r", psHooks->pvUserData);
+    if (pfCPG == SHPLIB_NULLPTR)
     {
         memcpy(pszFullname + nLenWithoutExtension, ".CPG", 5);
-        pfCPG = psHooks->FOpen( pszFullname, "r" );
+        pfCPG = psHooks->FOpen(pszFullname, "r", psHooks->pvUserData);
     }
 
-    free( pszFullname );
+    free(pszFullname);
 
-    if( psDBF->fp == SHPLIB_NULLPTR )
+    if (psDBF->fp == SHPLIB_NULLPTR)
     {
-        free( psDBF );
-        if( pfCPG ) psHooks->FClose( pfCPG );
+        free(psDBF);
+        if (pfCPG)
+            psHooks->FClose(pfCPG);
         return SHPLIB_NULLPTR;
     }
 
@@ -589,84 +402,88 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     psDBF->nCurrentRecord = -1;
     psDBF->bCurrentRecordModified = FALSE;
 
-/* -------------------------------------------------------------------- */
-/*  Read Table Header info                                              */
-/* -------------------------------------------------------------------- */
-    pabyBuf = STATIC_CAST(unsigned char *, malloc(nBufSize));
-    if( psDBF->sHooks.FRead( pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp ) != 1 )
+    /* -------------------------------------------------------------------- */
+    /*  Read Table Header info                                              */
+    /* -------------------------------------------------------------------- */
+    const int nBufSize = 500;
+    unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(nBufSize));
+    if (psDBF->sHooks.FRead(pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp) != 1)
     {
-        psDBF->sHooks.FClose( psDBF->fp );
-        if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
-        free( pabyBuf );
-        free( psDBF );
+        psDBF->sHooks.FClose(psDBF->fp);
+        if (pfCPG)
+            psDBF->sHooks.FClose(pfCPG);
+        free(pabyBuf);
+        free(psDBF);
         return SHPLIB_NULLPTR;
     }
 
     DBFSetLastModifiedDate(psDBF, pabyBuf[1], pabyBuf[2], pabyBuf[3]);
 
-    psDBF->nRecords =
-     pabyBuf[4]|(pabyBuf[5]<<8)|(pabyBuf[6]<<16)|((pabyBuf[7]&0x7f)<<24);
+    psDBF->nRecords = pabyBuf[4] | (pabyBuf[5] << 8) | (pabyBuf[6] << 16) |
+                      ((pabyBuf[7] & 0x7f) << 24);
 
-    psDBF->nHeaderLength = nHeadLen = pabyBuf[8]|(pabyBuf[9]<<8);
-    psDBF->nRecordLength = pabyBuf[10]|(pabyBuf[11]<<8);
+    const int nHeadLen = pabyBuf[8] | (pabyBuf[9] << 8);
+    psDBF->nHeaderLength = nHeadLen;
+    psDBF->nRecordLength = pabyBuf[10] | (pabyBuf[11] << 8);
     psDBF->iLanguageDriver = pabyBuf[29];
 
     if (psDBF->nRecordLength == 0 || nHeadLen < XBASE_FILEHDR_SZ)
     {
-        psDBF->sHooks.FClose( psDBF->fp );
-        if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
-        free( pabyBuf );
-        free( psDBF );
+        psDBF->sHooks.FClose(psDBF->fp);
+        if (pfCPG)
+            psDBF->sHooks.FClose(pfCPG);
+        free(pabyBuf);
+        free(psDBF);
         return SHPLIB_NULLPTR;
     }
 
-    psDBF->nFields = nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
+    const int nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
+    psDBF->nFields = nFields;
 
     /* coverity[tainted_data] */
     psDBF->pszCurrentRecord = STATIC_CAST(char *, malloc(psDBF->nRecordLength));
 
-/* -------------------------------------------------------------------- */
-/*  Figure out the code page from the LDID and CPG                      */
-/* -------------------------------------------------------------------- */
-
+    /* -------------------------------------------------------------------- */
+    /*  Figure out the code page from the LDID and CPG                      */
+    /* -------------------------------------------------------------------- */
     psDBF->pszCodePage = SHPLIB_NULLPTR;
-    if( pfCPG )
+    if (pfCPG)
     {
-        size_t n;
-        memset( pabyBuf, 0, nBufSize);
-        psDBF->sHooks.FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
-        n = strcspn( REINTERPRET_CAST(char *, pabyBuf), "\n\r" );
-        if( n > 0 )
+        memset(pabyBuf, 0, nBufSize);
+        psDBF->sHooks.FRead(pabyBuf, 1, nBufSize - 1, pfCPG);
+        const size_t n = strcspn(REINTERPRET_CAST(char *, pabyBuf), "\n\r");
+        if (n > 0)
         {
             pabyBuf[n] = '\0';
             psDBF->pszCodePage = STATIC_CAST(char *, malloc(n + 1));
-            memcpy( psDBF->pszCodePage, pabyBuf, n + 1 );
+            memcpy(psDBF->pszCodePage, pabyBuf, n + 1);
         }
-               psDBF->sHooks.FClose( pfCPG );
+        psDBF->sHooks.FClose(pfCPG);
     }
-    if( psDBF->pszCodePage == SHPLIB_NULLPTR && pabyBuf[29] != 0 )
+    if (psDBF->pszCodePage == SHPLIB_NULLPTR && pabyBuf[29] != 0)
     {
-        snprintf( REINTERPRET_CAST(char *, pabyBuf), nBufSize, "LDID/%d", psDBF->iLanguageDriver );
-        psDBF->pszCodePage = STATIC_CAST(char *, malloc(strlen(REINTERPRET_CAST(char*, pabyBuf)) + 1));
-        strcpy( psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf) );
+        snprintf(REINTERPRET_CAST(char *, pabyBuf), nBufSize, "LDID/%d",
+                 psDBF->iLanguageDriver);
+        psDBF->pszCodePage = STATIC_CAST(
+            char *, malloc(strlen(REINTERPRET_CAST(char *, pabyBuf)) + 1));
+        strcpy(psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf));
     }
 
-/* -------------------------------------------------------------------- */
-/*  Read in Field Definitions                                           */
-/* -------------------------------------------------------------------- */
-
-    pabyBuf = STATIC_CAST(unsigned char *, SfRealloc(pabyBuf,nHeadLen));
+    /* -------------------------------------------------------------------- */
+    /*  Read in Field Definitions                                           */
+    /* -------------------------------------------------------------------- */
+    pabyBuf = STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
     psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf);
 
-    psDBF->sHooks.FSeek( psDBF->fp, XBASE_FILEHDR_SZ, 0 );
-    if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-XBASE_FILEHDR_SZ, 1,
-                             psDBF->fp ) != 1 )
+    psDBF->sHooks.FSeek(psDBF->fp, XBASE_FILEHDR_SZ, 0);
+    if (psDBF->sHooks.FRead(pabyBuf, nHeadLen - XBASE_FILEHDR_SZ, 1,
+                            psDBF->fp) != 1)
     {
-        psDBF->sHooks.FClose( psDBF->fp );
-        free( pabyBuf );
-        free( psDBF->pszCurrentRecord );
-        free( psDBF->pszCodePage );
-        free( psDBF );
+        psDBF->sHooks.FClose(psDBF->fp);
+        free(pabyBuf);
+        free(psDBF->pszCurrentRecord);
+        free(psDBF->pszCodePage);
+        free(psDBF);
         return SHPLIB_NULLPTR;
     }
 
@@ -675,105 +492,107 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     psDBF->panFieldDecimals = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
     psDBF->pachFieldType = STATIC_CAST(char *, malloc(sizeof(char) * nFields));
 
-    for( iField = 0; iField < nFields; iField++ )
+    for (int iField = 0; iField < nFields; iField++)
     {
-       unsigned char           *pabyFInfo;
-
-       pabyFInfo = pabyBuf+iField*XBASE_FLDHDR_SZ;
-        if( pabyFInfo[0] == HEADER_RECORD_TERMINATOR )
+        unsigned char *pabyFInfo = pabyBuf + iField * XBASE_FLDHDR_SZ;
+        if (pabyFInfo[0] == HEADER_RECORD_TERMINATOR)
         {
             psDBF->nFields = iField;
             break;
         }
 
-       if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
-       {
-           psDBF->panFieldSize[iField] = pabyFInfo[16];
-           psDBF->panFieldDecimals[iField] = pabyFInfo[17];
-       }
-       else
-       {
-           psDBF->panFieldSize[iField] = pabyFInfo[16];
-           psDBF->panFieldDecimals[iField] = 0;
-
-/*
-** The following seemed to be used sometimes to handle files with long
-** string fields, but in other cases (such as bug 1202) the decimals field
-** just seems to indicate some sort of preferred formatting, not very
-** wide fields.  So I have disabled this code.  FrankW.
-           psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
-           psDBF->panFieldDecimals[iField] = 0;
-*/
-       }
-
-       psDBF->pachFieldType[iField] = STATIC_CAST(char, pabyFInfo[11]);
-       if( iField == 0 )
-           psDBF->panFieldOffset[iField] = 1;
-       else
-           psDBF->panFieldOffset[iField] =
-             psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
+        if (pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F')
+        {
+            psDBF->panFieldSize[iField] = pabyFInfo[16];
+            psDBF->panFieldDecimals[iField] = pabyFInfo[17];
+        }
+        else
+        {
+            psDBF->panFieldSize[iField] = pabyFInfo[16];
+            psDBF->panFieldDecimals[iField] = 0;
+
+            /*
+            ** The following seemed to be used sometimes to handle files with
+            long
+            ** string fields, but in other cases (such as bug 1202) the decimals
+            field
+            ** just seems to indicate some sort of preferred formatting, not
+            very
+            ** wide fields.  So I have disabled this code.  FrankW.
+                    psDBF->panFieldSize[iField] = pabyFInfo[16] +
+            pabyFInfo[17]*256; psDBF->panFieldDecimals[iField] = 0;
+            */
+        }
+
+        psDBF->pachFieldType[iField] = STATIC_CAST(char, pabyFInfo[11]);
+        if (iField == 0)
+            psDBF->panFieldOffset[iField] = 1;
+        else
+            psDBF->panFieldOffset[iField] = psDBF->panFieldOffset[iField - 1] +
+                                            psDBF->panFieldSize[iField - 1];
     }
 
     /* Check that the total width of fields does not exceed the record width */
-    if( psDBF->nFields > 0 &&
-        psDBF->panFieldOffset[psDBF->nFields-1] +
-            psDBF->panFieldSize[psDBF->nFields-1] > psDBF->nRecordLength )
+    if (psDBF->nFields > 0 && psDBF->panFieldOffset[psDBF->nFields - 1] +
+                                      psDBF->panFieldSize[psDBF->nFields - 1] >
+                                  psDBF->nRecordLength)
     {
-        DBFClose( psDBF );
+        DBFClose(psDBF);
         return SHPLIB_NULLPTR;
     }
 
-    DBFSetWriteEndOfFileChar( psDBF, TRUE );
+    DBFSetWriteEndOfFileChar(psDBF, TRUE);
+
+    psDBF->bRequireNextWriteSeek = TRUE;
 
-    return( psDBF );
+    return (psDBF);
 }
 
 /************************************************************************/
 /*                              DBFClose()                              */
 /************************************************************************/
 
-void SHPAPI_CALL
-DBFClose(DBFHandle psDBF)
+void SHPAPI_CALL DBFClose(DBFHandle psDBF)
 {
-    if( psDBF == SHPLIB_NULLPTR )
+    if (psDBF == SHPLIB_NULLPTR)
         return;
 
-/* -------------------------------------------------------------------- */
-/*      Write out header if not already written.                        */
-/* -------------------------------------------------------------------- */
-    if( psDBF->bNoHeader )
-        DBFWriteHeader( psDBF );
+    /* -------------------------------------------------------------------- */
+    /*      Write out header if not already written.                        */
+    /* -------------------------------------------------------------------- */
+    if (psDBF->bNoHeader)
+        DBFWriteHeader(psDBF);
 
-    CPL_IGNORE_RET_VAL_INT(DBFFlushRecord( psDBF ));
+    CPL_IGNORE_RET_VAL_INT(DBFFlushRecord(psDBF));
 
-/* -------------------------------------------------------------------- */
-/*      Update last access date, and number of records if we have      */
-/*     write access.                                                   */
-/* -------------------------------------------------------------------- */
-    if( psDBF->bUpdated )
-        DBFUpdateHeader( psDBF );
+    /* -------------------------------------------------------------------- */
+    /*      Update last access date, and number of records if we have       */
+    /*      write access.                                                   */
+    /* -------------------------------------------------------------------- */
+    if (psDBF->bUpdated)
+        DBFUpdateHeader(psDBF);
 
-/* -------------------------------------------------------------------- */
-/*      Close, and free resources.                                      */
-/* -------------------------------------------------------------------- */
-    psDBF->sHooks.FClose( psDBF->fp );
+    /* -------------------------------------------------------------------- */
+    /*      Close, and free resources.                                      */
+    /* -------------------------------------------------------------------- */
+    psDBF->sHooks.FClose(psDBF->fp);
 
-    if( psDBF->panFieldOffset != SHPLIB_NULLPTR )
+    if (psDBF->panFieldOffset != SHPLIB_NULLPTR)
     {
-        free( psDBF->panFieldOffset );
-        free( psDBF->panFieldSize );
-        free( psDBF->panFieldDecimals );
-        free( psDBF->pachFieldType );
+        free(psDBF->panFieldOffset);
+        free(psDBF->panFieldSize);
+        free(psDBF->panFieldDecimals);
+        free(psDBF->pachFieldType);
     }
 
-    if( psDBF->pszWorkField != SHPLIB_NULLPTR )
-        free( psDBF->pszWorkField );
+    if (psDBF->pszWorkField != SHPLIB_NULLPTR)
+        free(psDBF->pszWorkField);
 
-    free( psDBF->pszHeader );
-    free( psDBF->pszCurrentRecord );
-    free( psDBF->pszCodePage );
+    free(psDBF->pszHeader);
+    free(psDBF->pszCurrentRecord);
+    free(psDBF->pszCodePage);
 
-    free( psDBF );
+    free(psDBF);
 }
 
 /************************************************************************/
@@ -782,11 +601,9 @@ DBFClose(DBFHandle psDBF)
 /* Create a new .dbf file with default code page LDID/87 (0x57)         */
 /************************************************************************/
 
-DBFHandle SHPAPI_CALL
-DBFCreate( const char * pszFilename )
-
+DBFHandle SHPAPI_CALL DBFCreate(const char *pszFilename)
 {
-    return DBFCreateEx( pszFilename, "LDID/87" ); // 0x57
+    return DBFCreateEx(pszFilename, "LDID/87");  // 0x57
 }
 
 /************************************************************************/
@@ -795,15 +612,14 @@ DBFCreate( const char * pszFilename )
 /*      Create a new .dbf file.                                         */
 /************************************************************************/
 
-DBFHandle SHPAPI_CALL
-DBFCreateEx( const char * pszFilename, const char* pszCodePage )
-
+DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszFilename,
+                                  const char *pszCodePage)
 {
     SAHooks sHooks;
 
-    SASetupDefaultHooks( &sHooks );
+    SASetupDefaultHooks(&sHooks);
 
-    return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
+    return DBFCreateLL(pszFilename, pszCodePage, &sHooks);
 }
 
 /************************************************************************/
@@ -812,80 +628,69 @@ DBFCreateEx( const char * pszFilename, const char* pszCodePage )
 /*      Create a new .dbf file.                                         */
 /************************************************************************/
 
-DBFHandle SHPAPI_CALL
-DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHooks )
-
+DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
+                                  const char *pszCodePage,
+                                  const SAHooks *psHooks)
 {
-    DBFHandle  psDBF;
-    SAFile     fp;
-    char       *pszFullname;
-    int                ldid = -1;
-    char chZero = '\0';
-    int         nLenWithoutExtension;
-
-/* -------------------------------------------------------------------- */
-/*     Compute the base (layer) name.  If there is any extension       */
-/*     on the passed in filename we will strip it off.                 */
-/* -------------------------------------------------------------------- */
-    nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
-    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    /* -------------------------------------------------------------------- */
+    /*      Compute the base (layer) name.  If there is any extension       */
+    /*      on the passed in filename we will strip it off.                 */
+    /* -------------------------------------------------------------------- */
+    const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
+    char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
     memcpy(pszFullname, pszFilename, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
 
-/* -------------------------------------------------------------------- */
-/*      Create the file.                                                */
-/* -------------------------------------------------------------------- */
-    fp = psHooks->FOpen( pszFullname, "wb" );
-    if( fp == SHPLIB_NULLPTR )
-    {
-        free( pszFullname );
-        return SHPLIB_NULLPTR;
-    }
-
-    psHooks->FWrite( &chZero, 1, 1, fp );
-    psHooks->FClose( fp );
-
-    fp = psHooks->FOpen( pszFullname, "rb+" );
-    if( fp == SHPLIB_NULLPTR )
+    /* -------------------------------------------------------------------- */
+    /*      Create the file.                                                */
+    /* -------------------------------------------------------------------- */
+    SAFile fp = psHooks->FOpen(pszFullname, "wb+", psHooks->pvUserData);
+    if (fp == SHPLIB_NULLPTR)
     {
-        free( pszFullname );
+        free(pszFullname);
         return SHPLIB_NULLPTR;
     }
 
     memcpy(pszFullname + nLenWithoutExtension, ".cpg", 5);
-    if( pszCodePage != SHPLIB_NULLPTR )
+    int ldid = -1;
+    if (pszCodePage != SHPLIB_NULLPTR)
     {
-        if( strncmp( pszCodePage, "LDID/", 5 ) == 0 )
+        if (strncmp(pszCodePage, "LDID/", 5) == 0)
         {
-            ldid = atoi( pszCodePage + 5 );
-            if( ldid > 255 )
-                ldid = -1; // don't use 0 to indicate out of range as LDID/0 is a valid one
+            ldid = atoi(pszCodePage + 5);
+            if (ldid > 255)
+                ldid = -1;  // don't use 0 to indicate out of range as LDID/0 is
+                            // a valid one
         }
-        if( ldid < 0 )
+        if (ldid < 0)
         {
-            SAFile fpCPG = psHooks->FOpen( pszFullname, "w" );
-            psHooks->FWrite( CONST_CAST(void*, STATIC_CAST(const void*, pszCodePage)), strlen(pszCodePage), 1, fpCPG );
-            psHooks->FClose( fpCPG );
+            SAFile fpCPG =
+                psHooks->FOpen(pszFullname, "w", psHooks->pvUserData);
+            psHooks->FWrite(
+                CONST_CAST(void *, STATIC_CAST(const void *, pszCodePage)),
+                strlen(pszCodePage), 1, fpCPG);
+            psHooks->FClose(fpCPG);
         }
     }
-    if( pszCodePage == SHPLIB_NULLPTR || ldid >= 0 )
+    if (pszCodePage == SHPLIB_NULLPTR || ldid >= 0)
     {
-        psHooks->Remove( pszFullname );
+        psHooks->Remove(pszFullname, psHooks->pvUserData);
     }
 
-    free( pszFullname );
+    free(pszFullname);
 
-/* -------------------------------------------------------------------- */
-/*     Create the info structure.                                      */
-/* -------------------------------------------------------------------- */
-    psDBF = STATIC_CAST(DBFHandle, calloc(1,sizeof(DBFInfo)));
+    /* -------------------------------------------------------------------- */
+    /*      Create the info structure.                                      */
+    /* -------------------------------------------------------------------- */
+    DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
 
-    memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
+    memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
     psDBF->fp = fp;
     psDBF->nRecords = 0;
     psDBF->nFields = 0;
     psDBF->nRecordLength = 1;
-    psDBF->nHeaderLength = XBASE_FILEHDR_SZ + 1; /* + 1 for HEADER_RECORD_TERMINATOR */
+    psDBF->nHeaderLength =
+        XBASE_FILEHDR_SZ + 1; /* + 1 for HEADER_RECORD_TERMINATOR */
 
     psDBF->panFieldOffset = SHPLIB_NULLPTR;
     psDBF->panFieldSize = SHPLIB_NULLPTR;
@@ -901,16 +706,19 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
 
     psDBF->iLanguageDriver = ldid > 0 ? ldid : 0;
     psDBF->pszCodePage = SHPLIB_NULLPTR;
-    if( pszCodePage )
+    if (pszCodePage)
     {
-        psDBF->pszCodePage = STATIC_CAST(char *, malloc( strlen(pszCodePage) + 1 ));
-        strcpy( psDBF->pszCodePage, pszCodePage );
+        psDBF->pszCodePage =
+            STATIC_CAST(char *, malloc(strlen(pszCodePage) + 1));
+        strcpy(psDBF->pszCodePage, pszCodePage);
     }
     DBFSetLastModifiedDate(psDBF, 95, 7, 26); /* dummy date */
 
     DBFSetWriteEndOfFileChar(psDBF, TRUE);
 
-    return( psDBF );
+    psDBF->bRequireNextWriteSeek = TRUE;
+
+    return (psDBF);
 }
 
 /************************************************************************/
@@ -919,24 +727,22 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
 /*      Add a field to a newly created .dbf or to an existing one       */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFAddField(DBFHandle psDBF, const char * pszFieldName,
-            DBFFieldType eType, int nWidth, int nDecimals )
-
+int SHPAPI_CALL DBFAddField(DBFHandle psDBF, const char *pszFieldName,
+                            DBFFieldType eType, int nWidth, int nDecimals)
 {
-    char chNativeType = 'C';
+    char chNativeType;
 
-    if( eType == FTLogical )
+    if (eType == FTLogical)
         chNativeType = 'L';
-    else if( eType == FTDate )
-       chNativeType = 'D';
-    else if( eType == FTString )
+    else if (eType == FTDate)
+        chNativeType = 'D';
+    else if (eType == FTString)
         chNativeType = 'C';
     else
         chNativeType = 'N';
 
-    return DBFAddNativeFieldType( psDBF, pszFieldName, chNativeType,
-                                  nWidth, nDecimals );
+    return DBFAddNativeFieldType(psDBF, pszFieldName, chNativeType, nWidth,
+                                 nDecimals);
 }
 
 /************************************************************************/
@@ -947,15 +753,15 @@ static char DBFGetNullCharacter(char chType)
 {
     switch (chType)
     {
-      case 'N':
-      case 'F':
-        return '*';
-      case 'D':
-        return '0';
-      case 'L':
-       return '?';
-      default:
-       return ' ';
+        case 'N':
+        case 'F':
+            return '*';
+        case 'D':
+            return '0';
+        case 'L':
+            return '?';
+        default:
+            return ' ';
     }
 }
 
@@ -966,102 +772,93 @@ static char DBFGetNullCharacter(char chType)
 /*      are written.                                                    */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
-                      char chType, int nWidth, int nDecimals )
-
+int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
+                                      char chType, int nWidth, int nDecimals)
 {
-    char       *pszFInfo;
-    int                i;
-    int         nOldRecordLength, nOldHeaderLength;
-    char        *pszRecord;
-    char        chFieldFill;
-    SAOffset    nRecordOffset;
-
     /* make sure that everything is written in .dbf */
-    if( !DBFFlushRecord( psDBF ) )
+    if (!DBFFlushRecord(psDBF))
         return -1;
 
-    if( psDBF->nHeaderLength + XBASE_FLDHDR_SZ > 65535 )
+    if (psDBF->nHeaderLength + XBASE_FLDHDR_SZ > 65535)
     {
         char szMessage[128];
-        snprintf( szMessage, sizeof(szMessage),
-                  "Cannot add field %s. Header length limit reached "
-                  "(max 65535 bytes, 2046 fields).",
-                  pszFieldName );
-        psDBF->sHooks.Error( szMessage );
+        snprintf(szMessage, sizeof(szMessage),
+                 "Cannot add field %s. Header length limit reached "
+                 "(max 65535 bytes, 2046 fields).",
+                 pszFieldName);
+        psDBF->sHooks.Error(szMessage);
         return -1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do some checking to ensure we can add records to this file.     */
-/* -------------------------------------------------------------------- */
-    if( nWidth < 1 )
+    /* -------------------------------------------------------------------- */
+    /*      Do some checking to ensure we can add records to this file.     */
+    /* -------------------------------------------------------------------- */
+    if (nWidth < 1)
         return -1;
 
-    if( nWidth > XBASE_FLD_MAX_WIDTH )
+    if (nWidth > XBASE_FLD_MAX_WIDTH)
         nWidth = XBASE_FLD_MAX_WIDTH;
 
-    if( psDBF->nRecordLength + nWidth > 65535 )
+    if (psDBF->nRecordLength + nWidth > 65535)
     {
         char szMessage[128];
-        snprintf( szMessage, sizeof(szMessage),
-                  "Cannot add field %s. Record length limit reached "
-                  "(max 65535 bytes).",
-                  pszFieldName );
-        psDBF->sHooks.Error( szMessage );
+        snprintf(szMessage, sizeof(szMessage),
+                 "Cannot add field %s. Record length limit reached "
+                 "(max 65535 bytes).",
+                 pszFieldName);
+        psDBF->sHooks.Error(szMessage);
         return -1;
     }
 
-    nOldRecordLength = psDBF->nRecordLength;
-    nOldHeaderLength = psDBF->nHeaderLength;
+    const int nOldRecordLength = psDBF->nRecordLength;
+    const int nOldHeaderLength = psDBF->nHeaderLength;
 
-/* -------------------------------------------------------------------- */
-/*      SfRealloc all the arrays larger to hold the additional field      */
-/*      information.                                                    */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      realloc all the arrays larger to hold the additional field      */
+    /*      information.                                                    */
+    /* -------------------------------------------------------------------- */
     psDBF->nFields++;
 
-    psDBF->panFieldOffset = STATIC_CAST(int *,
-        SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ));
+    psDBF->panFieldOffset = STATIC_CAST(
+        int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));
 
-    psDBF->panFieldSize = STATIC_CAST(int *,
-        SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ));
+    psDBF->panFieldSize = STATIC_CAST(
+        int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));
 
-    psDBF->panFieldDecimals = STATIC_CAST(int *,
-        SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ));
+    psDBF->panFieldDecimals = STATIC_CAST(
+        int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));
 
-    psDBF->pachFieldType = STATIC_CAST(char *,
-        SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ));
+    psDBF->pachFieldType = STATIC_CAST(
+        char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));
 
-/* -------------------------------------------------------------------- */
-/*      Assign the new field information fields.                        */
-/* -------------------------------------------------------------------- */
-    psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
+    /* -------------------------------------------------------------------- */
+    /*      Assign the new field information fields.                        */
+    /* -------------------------------------------------------------------- */
+    psDBF->panFieldOffset[psDBF->nFields - 1] = psDBF->nRecordLength;
     psDBF->nRecordLength += nWidth;
-    psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
-    psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
-    psDBF->pachFieldType[psDBF->nFields-1] = chType;
+    psDBF->panFieldSize[psDBF->nFields - 1] = nWidth;
+    psDBF->panFieldDecimals[psDBF->nFields - 1] = nDecimals;
+    psDBF->pachFieldType[psDBF->nFields - 1] = chType;
 
-/* -------------------------------------------------------------------- */
-/*      Extend the required header information.                         */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      Extend the required header information.                         */
+    /* -------------------------------------------------------------------- */
     psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
     psDBF->bUpdated = FALSE;
 
-    psDBF->pszHeader = STATIC_CAST(char *, SfRealloc(psDBF->pszHeader,
-                                          psDBF->nFields*XBASE_FLDHDR_SZ));
+    psDBF->pszHeader = STATIC_CAST(
+        char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));
 
-    pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields-1);
+    char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields - 1);
 
-    for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
+    for (int i = 0; i < XBASE_FLDHDR_SZ; i++)
         pszFInfo[i] = '\0';
 
-    strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
+    strncpy(pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE);
 
-    pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
+    pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields - 1];
 
-    if( chType == 'C' )
+    if (chType == 'C')
     {
         pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
         pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
@@ -1072,52 +869,61 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
         pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Make the current record buffer appropriately larger.            */
-/* -------------------------------------------------------------------- */
-    psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
-                                                 psDBF->nRecordLength));
+    /* -------------------------------------------------------------------- */
+    /*      Make the current record buffer appropriately larger.            */
+    /* -------------------------------------------------------------------- */
+    psDBF->pszCurrentRecord = STATIC_CAST(
+        char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
 
     /* we're done if dealing with new .dbf */
-    if( psDBF->bNoHeader )
-        return( psDBF->nFields - 1 );
+    if (psDBF->bNoHeader)
+        return (psDBF->nFields - 1);
 
-/* -------------------------------------------------------------------- */
-/*      For existing .dbf file, shift records                           */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      For existing .dbf file, shift records                           */
+    /* -------------------------------------------------------------------- */
 
     /* alloc record */
-    pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+    char *pszRecord =
+        STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
 
-    chFieldFill = DBFGetNullCharacter(chType);
+    const char chFieldFill = DBFGetNullCharacter(chType);
 
-    for (i = psDBF->nRecords-1; i >= 0; --i)
+    SAOffset nRecordOffset;
+    for (int i = psDBF->nRecords - 1; i >= 0; --i)
     {
-        nRecordOffset = nOldRecordLength * STATIC_CAST(SAOffset, i) + nOldHeaderLength;
+        nRecordOffset =
+            nOldRecordLength * STATIC_CAST(SAOffset, i) + nOldHeaderLength;
 
         /* load record */
-        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-        psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+        psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+        if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1, psDBF->fp) != 1)
+        {
+            free(pszRecord);
+            return -1;
+        }
 
         /* set new field's value to NULL */
         memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
 
-        nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, i) + psDBF->nHeaderLength;
+        nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, i) +
+                        psDBF->nHeaderLength;
 
         /* move record to the new place*/
-        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-        psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+        psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+        psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
     }
 
-    if( psDBF->bWriteEndOfFileChar )
+    if (psDBF->bWriteEndOfFileChar)
     {
         char ch = END_OF_FILE_CHARACTER;
 
         nRecordOffset =
-            psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+            psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+            psDBF->nHeaderLength;
 
-        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-        psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+        psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+        psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
     }
 
     /* free record */
@@ -1125,13 +931,13 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
 
     /* force update of header with new header, record length and new field */
     psDBF->bNoHeader = TRUE;
-    DBFUpdateHeader( psDBF );
+    DBFUpdateHeader(psDBF);
 
     psDBF->nCurrentRecord = -1;
     psDBF->bCurrentRecordModified = FALSE;
     psDBF->bUpdated = TRUE;
 
-    return( psDBF->nFields-1 );
+    return (psDBF->nFields - 1);
 }
 
 /************************************************************************/
@@ -1141,64 +947,64 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
 /************************************************************************/
 
 static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
-                              char chReqType )
-
+                              char chReqType)
 {
-    unsigned char      *pabyRec;
-    void       *pReturnField = SHPLIB_NULLPTR;
-
-/* -------------------------------------------------------------------- */
-/*      Verify selection.                                               */
-/* -------------------------------------------------------------------- */
-    if( hEntity < 0 || hEntity >= psDBF->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Verify selection.                                               */
+    /* -------------------------------------------------------------------- */
+    if (hEntity < 0 || hEntity >= psDBF->nRecords)
         return SHPLIB_NULLPTR;
 
-    if( iField < 0 || iField >= psDBF->nFields )
+    if (iField < 0 || iField >= psDBF->nFields)
         return SHPLIB_NULLPTR;
 
-/* -------------------------------------------------------------------- */
-/*     Have we read the record?                                        */
-/* -------------------------------------------------------------------- */
-    if( !DBFLoadRecord( psDBF, hEntity ) )
+    /* -------------------------------------------------------------------- */
+    /*     Have we read the record?                                         */
+    /* -------------------------------------------------------------------- */
+    if (!DBFLoadRecord(psDBF, hEntity))
         return SHPLIB_NULLPTR;
 
-    pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
+    const unsigned char *pabyRec =
+        REINTERPRET_CAST(const unsigned char *, psDBF->pszCurrentRecord);
 
-/* -------------------------------------------------------------------- */
-/*      Ensure we have room to extract the target field.                */
-/* -------------------------------------------------------------------- */
-    if( psDBF->panFieldSize[iField] >= psDBF->nWorkFieldLength )
+    /* -------------------------------------------------------------------- */
+    /*      Ensure we have room to extract the target field.                */
+    /* -------------------------------------------------------------------- */
+    if (psDBF->panFieldSize[iField] >= psDBF->nWorkFieldLength)
     {
         psDBF->nWorkFieldLength = psDBF->panFieldSize[iField] + 100;
-        if( psDBF->pszWorkField == SHPLIB_NULLPTR )
-            psDBF->pszWorkField = STATIC_CAST(char *, malloc(psDBF->nWorkFieldLength));
+        if (psDBF->pszWorkField == SHPLIB_NULLPTR)
+            psDBF->pszWorkField =
+                STATIC_CAST(char *, malloc(psDBF->nWorkFieldLength));
         else
-            psDBF->pszWorkField = STATIC_CAST(char *, realloc(psDBF->pszWorkField,
-                                                   psDBF->nWorkFieldLength));
+            psDBF->pszWorkField = STATIC_CAST(
+                char *, realloc(psDBF->pszWorkField, psDBF->nWorkFieldLength));
     }
 
-/* -------------------------------------------------------------------- */
-/*     Extract the requested field.                                    */
-/* -------------------------------------------------------------------- */
-    memcpy( psDBF->pszWorkField,
-            REINTERPRET_CAST(const char *, pabyRec) + psDBF->panFieldOffset[iField],
-            psDBF->panFieldSize[iField] );
+    /* -------------------------------------------------------------------- */
+    /*      Extract the requested field.                                    */
+    /* -------------------------------------------------------------------- */
+    memcpy(psDBF->pszWorkField,
+           REINTERPRET_CAST(const char *, pabyRec) +
+               psDBF->panFieldOffset[iField],
+           psDBF->panFieldSize[iField]);
     psDBF->pszWorkField[psDBF->panFieldSize[iField]] = '\0';
 
-    pReturnField = psDBF->pszWorkField;
+    void *pReturnField = psDBF->pszWorkField;
 
-/* -------------------------------------------------------------------- */
-/*      Decode the field.                                               */
-/* -------------------------------------------------------------------- */
-    if( chReqType == 'I' )
+    /* -------------------------------------------------------------------- */
+    /*      Decode the field.                                               */
+    /* -------------------------------------------------------------------- */
+    if (chReqType == 'I')
     {
         psDBF->fieldValue.nIntField = atoi(psDBF->pszWorkField);
 
         pReturnField = &(psDBF->fieldValue.nIntField);
     }
-    else if( chReqType == 'N' )
+    else if (chReqType == 'N')
     {
-        psDBF->fieldValue.dfDoubleField = psDBF->sHooks.Atof(psDBF->pszWorkField);
+        psDBF->fieldValue.dfDoubleField =
+            psDBF->sHooks.Atof(psDBF->pszWorkField);
 
         pReturnField = &(psDBF->fieldValue.dfDoubleField);
     }
@@ -1209,17 +1015,17 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 #ifdef TRIM_DBF_WHITESPACE
     else
     {
-        char   *pchSrc, *pchDst;
+        char *pchSrc = psDBF->pszWorkField;
+        char *pchDst = pchSrc;
 
-        pchDst = pchSrc = psDBF->pszWorkField;
-        while( *pchSrc == ' ' )
+        while (*pchSrc == ' ')
             pchSrc++;
 
-        while( *pchSrc != '\0' )
+        while (*pchSrc != '\0')
             *(pchDst++) = *(pchSrc++);
         *pchDst = '\0';
 
-        while( pchDst != psDBF->pszWorkField && *(--pchDst) == ' ' )
+        while (pchDst != psDBF->pszWorkField && *(--pchDst) == ' ')
             *pchDst = '\0';
     }
 #endif
@@ -1233,15 +1039,13 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 /*      Read an integer attribute.                                      */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
-
+int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle psDBF, int iRecord,
+                                        int iField)
 {
-    int        *pnValue;
-
-    pnValue = STATIC_CAST(int *, DBFReadAttribute( psDBF, iRecord, iField, 'I' ));
+    int *pnValue =
+        STATIC_CAST(int *, DBFReadAttribute(psDBF, iRecord, iField, 'I'));
 
-    if( pnValue == SHPLIB_NULLPTR )
+    if (pnValue == SHPLIB_NULLPTR)
         return 0;
     else
         return *pnValue;
@@ -1253,18 +1057,16 @@ DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
 /*      Read a double attribute.                                        */
 /************************************************************************/
 
-double SHPAPI_CALL
-DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
-
+double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle psDBF, int iRecord,
+                                          int iField)
 {
-    double     *pdValue;
-
-    pdValue = STATIC_CAST(double *, DBFReadAttribute( psDBF, iRecord, iField, 'N' ));
+    double *pdValue =
+        STATIC_CAST(double *, DBFReadAttribute(psDBF, iRecord, iField, 'N'));
 
-    if( pdValue == SHPLIB_NULLPTR )
+    if (pdValue == SHPLIB_NULLPTR)
         return 0.0;
     else
-        return *pdValue ;
+        return *pdValue;
 }
 
 /************************************************************************/
@@ -1274,10 +1076,11 @@ DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
 /************************************************************************/
 
 const char SHPAPI_CALL1(*)
-DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
+    DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField)
 
 {
-    return STATIC_CAST(const char *, DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
+    return STATIC_CAST(const char *,
+                       DBFReadAttribute(psDBF, iRecord, iField, 'C'));
 }
 
 /************************************************************************/
@@ -1287,56 +1090,59 @@ DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
 /************************************************************************/
 
 const char SHPAPI_CALL1(*)
-DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
+    DBFReadLogicalAttribute(DBFHandle psDBF, int iRecord, int iField)
 
 {
-    return STATIC_CAST(const char *, DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
+    return STATIC_CAST(const char *,
+                       DBFReadAttribute(psDBF, iRecord, iField, 'L'));
 }
 
-
 /************************************************************************/
 /*                         DBFIsValueNULL()                             */
 /*                                                                      */
 /*      Return TRUE if the passed string is NULL.                       */
 /************************************************************************/
 
-static int DBFIsValueNULL( char chType, const char* pszValue )
+static bool DBFIsValueNULL(char chType, const char *pszValue)
 {
-    int i;
-
-    if( pszValue == SHPLIB_NULLPTR )
-        return TRUE;
+    if (pszValue == SHPLIB_NULLPTR)
+        return true;
 
-    switch(chType)
+    switch (chType)
     {
-      case 'N':
-      case 'F':
-        /*
-        ** We accept all asterisks or all blanks as NULL
-        ** though according to the spec I think it should be all
-        ** asterisks.
-        */
-        if( pszValue[0] == '*' )
-            return TRUE;
-
-        for( i = 0; pszValue[i] != '\0'; i++ )
-        {
-            if( pszValue[i] != ' ' )
-                return FALSE;
-        }
-        return TRUE;
-
-      case 'D':
-        /* NULL date fields have value "00000000" */
-        return strncmp(pszValue,"00000000",8) == 0;
-
-      case 'L':
-        /* NULL boolean fields have value "?" */
-        return pszValue[0] == '?';
-
-      default:
-        /* empty string fields are considered NULL */
-        return strlen(pszValue) == 0;
+        case 'N':
+        case 'F':
+            /*
+            ** We accept all asterisks or all blanks as NULL
+            ** though according to the spec I think it should be all
+            ** asterisks.
+            */
+            if (pszValue[0] == '*')
+                return true;
+
+            for (int i = 0; pszValue[i] != '\0'; i++)
+            {
+                if (pszValue[i] != ' ')
+                    return false;
+            }
+            return true;
+
+        case 'D':
+            /* NULL date fields have value "00000000" */
+            /* Some DBF files have fields filled with spaces */
+            /* (trimmed by DBFReadStringAttribute) to indicate null */
+            /* values for dates (#4265). */
+            /* And others have '       0': https://lists.osgeo.org/pipermail/gdal-dev/2023-November/058010.html */
+            return strncmp(pszValue, "00000000", 8) == 0 ||
+                   strcmp(pszValue, " ") == 0 || strcmp(pszValue, "0") == 0;
+
+        case 'L':
+            /* NULL boolean fields have value "?" */
+            return pszValue[0] == '?';
+
+        default:
+            /* empty string fields are considered NULL */
+            return strlen(pszValue) == 0;
     }
 }
 
@@ -1348,18 +1154,14 @@ static int DBFIsValueNULL( char chType, const char* pszValue )
 /*      Contributed by Jim Matthews.                                    */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
-
+int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField)
 {
-    const char *pszValue;
-
-    pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+    const char *pszValue = DBFReadStringAttribute(psDBF, iRecord, iField);
 
-    if( pszValue == SHPLIB_NULLPTR )
+    if (pszValue == SHPLIB_NULLPTR)
         return TRUE;
 
-    return DBFIsValueNULL( psDBF->pachFieldType[iField], pszValue );
+    return DBFIsValueNULL(psDBF->pachFieldType[iField], pszValue);
 }
 
 /************************************************************************/
@@ -1368,11 +1170,10 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
 /*      Return the number of fields in this table.                      */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFGetFieldCount( DBFHandle psDBF )
+int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
 
 {
-    return( psDBF->nFields );
+    return (psDBF->nFields);
 }
 
 /************************************************************************/
@@ -1381,11 +1182,10 @@ DBFGetFieldCount( DBFHandle psDBF )
 /*      Return the number of records in this table.                     */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFGetRecordCount( DBFHandle psDBF )
+int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
 
 {
-    return( psDBF->nRecords );
+    return (psDBF->nRecords);
 }
 
 /************************************************************************/
@@ -1396,168 +1196,179 @@ DBFGetRecordCount( DBFHandle psDBF )
 /*      bytes long.                                                     */
 /************************************************************************/
 
-DBFFieldType SHPAPI_CALL
-DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
-                 int * pnWidth, int * pnDecimals )
+DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField,
+                                         char *pszFieldName, int *pnWidth,
+                                         int *pnDecimals)
 
 {
-    if( iField < 0 || iField >= psDBF->nFields )
-        return( FTInvalid );
+    if (iField < 0 || iField >= psDBF->nFields)
+        return (FTInvalid);
 
-    if( pnWidth != SHPLIB_NULLPTR )
+    if (pnWidth != SHPLIB_NULLPTR)
         *pnWidth = psDBF->panFieldSize[iField];
 
-    if( pnDecimals != SHPLIB_NULLPTR )
+    if (pnDecimals != SHPLIB_NULLPTR)
         *pnDecimals = psDBF->panFieldDecimals[iField];
 
-    if( pszFieldName != SHPLIB_NULLPTR )
+    if (pszFieldName != SHPLIB_NULLPTR)
     {
-       int     i;
-
-       strncpy( pszFieldName, STATIC_CAST(char *,psDBF->pszHeader)+iField*XBASE_FLDHDR_SZ,
-                 XBASE_FLDNAME_LEN_READ );
-       pszFieldName[XBASE_FLDNAME_LEN_READ] = '\0';
-       for( i = XBASE_FLDNAME_LEN_READ - 1; i > 0 && pszFieldName[i] == ' '; i-- )
-           pszFieldName[i] = '\0';
+        strncpy(pszFieldName,
+                STATIC_CAST(char *, psDBF->pszHeader) +
+                    iField * XBASE_FLDHDR_SZ,
+                XBASE_FLDNAME_LEN_READ);
+        pszFieldName[XBASE_FLDNAME_LEN_READ] = '\0';
+        for (int i = XBASE_FLDNAME_LEN_READ - 1;
+             i > 0 && pszFieldName[i] == ' '; i--)
+            pszFieldName[i] = '\0';
     }
 
-    if ( psDBF->pachFieldType[iField] == 'L' )
-       return( FTLogical );
+    if (psDBF->pachFieldType[iField] == 'L')
+        return (FTLogical);
 
-    else if( psDBF->pachFieldType[iField] == 'D' )
-       return( FTDate );
+    else if (psDBF->pachFieldType[iField] == 'D')
+        return (FTDate);
 
-    else if( psDBF->pachFieldType[iField] == 'N'
-             || psDBF->pachFieldType[iField] == 'F' )
+    else if (psDBF->pachFieldType[iField] == 'N' ||
+             psDBF->pachFieldType[iField] == 'F')
     {
-       if( psDBF->panFieldDecimals[iField] > 0
-            || psDBF->panFieldSize[iField] >= 10 )
-           return( FTDouble );
-       else
-           return( FTInteger );
+        if (psDBF->panFieldDecimals[iField] > 0 ||
+            psDBF->panFieldSize[iField] >= 10)
+            return (FTDouble);
+        else
+            return (FTInteger);
     }
     else
     {
-       return( FTString );
+        return (FTString);
     }
 }
 
 /************************************************************************/
 /*                         DBFWriteAttribute()                          */
-/*                                                                     */
-/*     Write an attribute record to the file.                          */
+/*                                                                      */
+/*      Write an attribute record to the file.                          */
 /************************************************************************/
 
-static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
-                            void * pValue )
-
+static bool DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
+                              void *pValue)
 {
-    int                i, j, nRetResult = TRUE;
-    unsigned char      *pabyRec;
-    char       szSField[XBASE_FLD_MAX_WIDTH+1], szFormat[20];
-
-/* -------------------------------------------------------------------- */
-/*     Is this a valid record?                                         */
-/* -------------------------------------------------------------------- */
-    if( hEntity < 0 || hEntity > psDBF->nRecords )
-        return( FALSE );
+    /* -------------------------------------------------------------------- */
+    /*      Is this a valid record?                                         */
+    /* -------------------------------------------------------------------- */
+    if (hEntity < 0 || hEntity > psDBF->nRecords)
+        return false;
 
-    if( psDBF->bNoHeader )
+    if (psDBF->bNoHeader)
         DBFWriteHeader(psDBF);
 
-/* -------------------------------------------------------------------- */
-/*      Is this a brand new record?                                     */
-/* -------------------------------------------------------------------- */
-    if( hEntity == psDBF->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Is this a brand new record?                                     */
+    /* -------------------------------------------------------------------- */
+    if (hEntity == psDBF->nRecords)
     {
-       if( !DBFFlushRecord( psDBF ) )
-            return FALSE;
+        if (!DBFFlushRecord(psDBF))
+            return false;
 
-       psDBF->nRecords++;
-       for( i = 0; i < psDBF->nRecordLength; i++ )
-           psDBF->pszCurrentRecord[i] = ' ';
+        psDBF->nRecords++;
+        for (int i = 0; i < psDBF->nRecordLength; i++)
+            psDBF->pszCurrentRecord[i] = ' ';
 
-       psDBF->nCurrentRecord = hEntity;
+        psDBF->nCurrentRecord = hEntity;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Is this an existing record, but different than the last one     */
-/*      we accessed?                                                    */
-/* -------------------------------------------------------------------- */
-    if( !DBFLoadRecord( psDBF, hEntity ) )
-        return FALSE;
+    /* -------------------------------------------------------------------- */
+    /*      Is this an existing record, but different than the last one     */
+    /*      we accessed?                                                    */
+    /* -------------------------------------------------------------------- */
+    if (!DBFLoadRecord(psDBF, hEntity))
+        return false;
 
-    pabyRec = REINTERPRET_CAST(unsigned char *,psDBF->pszCurrentRecord);
+    unsigned char *pabyRec =
+        REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
 
     psDBF->bCurrentRecordModified = TRUE;
     psDBF->bUpdated = TRUE;
 
-/* -------------------------------------------------------------------- */
-/*      Translate NULL value to valid DBF file representation.          */
-/*                                                                      */
-/*      Contributed by Jim Matthews.                                    */
-/* -------------------------------------------------------------------- */
-    if( pValue == SHPLIB_NULLPTR )
+    /* -------------------------------------------------------------------- */
+    /*      Translate NULL value to valid DBF file representation.          */
+    /*                                                                      */
+    /*      Contributed by Jim Matthews.                                    */
+    /* -------------------------------------------------------------------- */
+    if (pValue == SHPLIB_NULLPTR)
     {
-        memset( pabyRec+psDBF->panFieldOffset[iField],
-                DBFGetNullCharacter(psDBF->pachFieldType[iField]),
-                psDBF->panFieldSize[iField] );
-        return TRUE;
+        memset(pabyRec + psDBF->panFieldOffset[iField],
+               DBFGetNullCharacter(psDBF->pachFieldType[iField]),
+               psDBF->panFieldSize[iField]);
+        return true;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Assign all the record fields.                                   */
-/* -------------------------------------------------------------------- */
-    switch( psDBF->pachFieldType[iField] )
+    /* -------------------------------------------------------------------- */
+    /*      Assign all the record fields.                                   */
+    /* -------------------------------------------------------------------- */
+    bool nRetResult = true;
+
+    switch (psDBF->pachFieldType[iField])
     {
-      case 'D':
-      case 'N':
-      case 'F':
-      {
-        int            nWidth = psDBF->panFieldSize[iField];
-
-        if( STATIC_CAST(int,sizeof(szSField))-2 < nWidth )
-            nWidth = sizeof(szSField)-2;
-
-        snprintf( szFormat, sizeof(szFormat), "%%%d.%df",
-                    nWidth, psDBF->panFieldDecimals[iField] );
-        CPLsnprintf(szSField, sizeof(szSField), szFormat, *STATIC_CAST(double *, pValue) );
-        szSField[sizeof(szSField)-1] = '\0';
-        if( STATIC_CAST(int,strlen(szSField)) > psDBF->panFieldSize[iField] )
+        case 'D':
+        case 'N':
+        case 'F':
         {
-            szSField[psDBF->panFieldSize[iField]] = '\0';
-            nRetResult = FALSE;
-        }
-        strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
-            szSField, strlen(szSField) );
-        break;
-      }
-
-      case 'L':
-        if (psDBF->panFieldSize[iField] >= 1  &&
-            (*STATIC_CAST(char*,pValue) == 'F' || *STATIC_CAST(char*,pValue) == 'T'))
-            *(pabyRec+psDBF->panFieldOffset[iField]) = *STATIC_CAST(char*,pValue);
-        break;
-
-      default:
-       if( STATIC_CAST(int, strlen(STATIC_CAST(char *,pValue))) > psDBF->panFieldSize[iField] )
-        {
-           j = psDBF->panFieldSize[iField];
-            nRetResult = FALSE;
+            int nWidth = psDBF->panFieldSize[iField];
+
+            char szSField[XBASE_FLD_MAX_WIDTH + 1];
+            if (STATIC_CAST(int, sizeof(szSField)) - 2 < nWidth)
+                nWidth = sizeof(szSField) - 2;
+
+            char szFormat[20];
+            snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nWidth,
+                     psDBF->panFieldDecimals[iField]);
+            CPLsnprintf(szSField, sizeof(szSField), szFormat,
+                        *STATIC_CAST(double *, pValue));
+            szSField[sizeof(szSField) - 1] = '\0';
+            if (STATIC_CAST(int, strlen(szSField)) >
+                psDBF->panFieldSize[iField])
+            {
+                szSField[psDBF->panFieldSize[iField]] = '\0';
+                nRetResult = false;
+            }
+            memcpy(REINTERPRET_CAST(char *,
+                                    pabyRec + psDBF->panFieldOffset[iField]),
+                   szSField, strlen(szSField));
+            break;
         }
-       else
+
+        case 'L':
+            if (psDBF->panFieldSize[iField] >= 1 &&
+                (*STATIC_CAST(char *, pValue) == 'F' ||
+                 *STATIC_CAST(char *, pValue) == 'T'))
+                *(pabyRec + psDBF->panFieldOffset[iField]) =
+                    *STATIC_CAST(char *, pValue);
+            break;
+
+        default:
         {
-            memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
-                    psDBF->panFieldSize[iField] );
-           j = STATIC_CAST(int, strlen(STATIC_CAST(char *,pValue)));
-        }
+            int j;
+            if (STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) >
+                psDBF->panFieldSize[iField])
+            {
+                j = psDBF->panFieldSize[iField];
+                nRetResult = false;
+            }
+            else
+            {
+                memset(pabyRec + psDBF->panFieldOffset[iField], ' ',
+                       psDBF->panFieldSize[iField]);
+                j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
+            }
 
-       strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
-               STATIC_CAST(const char *, pValue), j );
-       break;
+            strncpy(REINTERPRET_CAST(char *,
+                                     pabyRec + psDBF->panFieldOffset[iField]),
+                    STATIC_CAST(const char *, pValue), j);
+            break;
+        }
     }
 
-    return( nRetResult );
+    return nRetResult;
 }
 
 /************************************************************************/
@@ -1568,66 +1379,68 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 /*      as is to the field position in the record.                      */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
-                              void * pValue )
-
+int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity,
+                                          int iField, const void *pValue)
 {
-    int                        i, j;
-    unsigned char      *pabyRec;
+    /* -------------------------------------------------------------------- */
+    /*      Is this a valid record?                                         */
+    /* -------------------------------------------------------------------- */
+    if (hEntity < 0 || hEntity > psDBF->nRecords)
+        return (FALSE);
 
-/* -------------------------------------------------------------------- */
-/*     Is this a valid record?                                         */
-/* -------------------------------------------------------------------- */
-    if( hEntity < 0 || hEntity > psDBF->nRecords )
-        return( FALSE );
-
-    if( psDBF->bNoHeader )
+    if (psDBF->bNoHeader)
         DBFWriteHeader(psDBF);
 
-/* -------------------------------------------------------------------- */
-/*      Is this a brand new record?                                     */
-/* -------------------------------------------------------------------- */
-    if( hEntity == psDBF->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Is this a brand new record?                                     */
+    /* -------------------------------------------------------------------- */
+    if (hEntity == psDBF->nRecords)
     {
-       if( !DBFFlushRecord( psDBF ) )
+        if (!DBFFlushRecord(psDBF))
             return FALSE;
 
-       psDBF->nRecords++;
-       for( i = 0; i < psDBF->nRecordLength; i++ )
-           psDBF->pszCurrentRecord[i] = ' ';
+        psDBF->nRecords++;
+        for (int i = 0; i < psDBF->nRecordLength; i++)
+            psDBF->pszCurrentRecord[i] = ' ';
 
-       psDBF->nCurrentRecord = hEntity;
+        psDBF->nCurrentRecord = hEntity;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Is this an existing record, but different than the last one     */
-/*      we accessed?                                                    */
-/* -------------------------------------------------------------------- */
-    if( !DBFLoadRecord( psDBF, hEntity ) )
+    /* -------------------------------------------------------------------- */
+    /*      Is this an existing record, but different than the last one     */
+    /*      we accessed?                                                    */
+    /* -------------------------------------------------------------------- */
+    if (!DBFLoadRecord(psDBF, hEntity))
         return FALSE;
 
-    pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
-
-/* -------------------------------------------------------------------- */
-/*      Assign all the record fields.                                   */
-/* -------------------------------------------------------------------- */
-    if( STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) > psDBF->panFieldSize[iField] )
-        j = psDBF->panFieldSize[iField];
-    else
+    if (iField >= 0)
     {
-        memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
-                psDBF->panFieldSize[iField] );
-        j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
-    }
+        unsigned char *pabyRec =
+            REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
+
+        /* -------------------------------------------------------------------- */
+        /*      Assign all the record fields.                                   */
+        /* -------------------------------------------------------------------- */
+        int j;
+        if (STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) >
+            psDBF->panFieldSize[iField])
+            j = psDBF->panFieldSize[iField];
+        else
+        {
+            memset(pabyRec + psDBF->panFieldOffset[iField], ' ',
+                   psDBF->panFieldSize[iField]);
+            j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
+        }
 
-    strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
-            STATIC_CAST(const char *, pValue), j );
+        strncpy(
+            REINTERPRET_CAST(char *, pabyRec + psDBF->panFieldOffset[iField]),
+            STATIC_CAST(const char *, pValue), j);
+    }
 
     psDBF->bCurrentRecordModified = TRUE;
     psDBF->bUpdated = TRUE;
 
-    return( TRUE );
+    return (TRUE);
 }
 
 /************************************************************************/
@@ -1636,12 +1449,11 @@ DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
 /*      Write a double attribute.                                       */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
-                         double dValue )
-
+int SHPAPI_CALL DBFWriteDoubleAttribute(DBFHandle psDBF, int iRecord,
+                                        int iField, double dValue)
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, &dValue) ) );
+    return (DBFWriteAttribute(psDBF, iRecord, iField,
+                              STATIC_CAST(void *, &dValue)));
 }
 
 /************************************************************************/
@@ -1650,14 +1462,13 @@ DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
 /*      Write a integer attribute.                                      */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
-                          int nValue )
-
+int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord,
+                                         int iField, int nValue)
 {
-    double     dValue = nValue;
+    double dValue = nValue;
 
-    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, &dValue) ) );
+    return (DBFWriteAttribute(psDBF, iRecord, iField,
+                              STATIC_CAST(void *, &dValue)));
 }
 
 /************************************************************************/
@@ -1666,12 +1477,13 @@ DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
 /*      Write a string attribute.                                       */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
-                         const char * pszValue )
+int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle psDBF, int iRecord,
+                                        int iField, const char *pszValue)
 
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, CONST_CAST(char*, pszValue))) );
+    return (
+        DBFWriteAttribute(psDBF, iRecord, iField,
+                          STATIC_CAST(void *, CONST_CAST(char *, pszValue))));
 }
 
 /************************************************************************/
@@ -1680,11 +1492,10 @@ DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
 /*      Write a string attribute.                                       */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
+int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField)
 
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, SHPLIB_NULLPTR ) );
+    return (DBFWriteAttribute(psDBF, iRecord, iField, SHPLIB_NULLPTR));
 }
 
 /************************************************************************/
@@ -1693,66 +1504,64 @@ DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
 /*      Write a logical attribute.                                      */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
-                      const char lValue)
+int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle psDBF, int iRecord,
+                                         int iField, const char lValue)
 
 {
-    return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, CONST_CAST(char*, &lValue)) ) );
+    return (
+        DBFWriteAttribute(psDBF, iRecord, iField,
+                          STATIC_CAST(void *, CONST_CAST(char *, &lValue))));
 }
 
 /************************************************************************/
 /*                         DBFWriteTuple()                              */
-/*                                                                     */
-/*     Write an attribute record to the file.                          */
+/*                                                                      */
+/*      Write an attribute record to the file.                          */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
-
+int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity,
+                              const void *pRawTuple)
 {
-    int                        i;
-    unsigned char      *pabyRec;
+    /* -------------------------------------------------------------------- */
+    /*      Is this a valid record?                                         */
+    /* -------------------------------------------------------------------- */
+    if (hEntity < 0 || hEntity > psDBF->nRecords)
+        return (FALSE);
 
-/* -------------------------------------------------------------------- */
-/*     Is this a valid record?                                         */
-/* -------------------------------------------------------------------- */
-    if( hEntity < 0 || hEntity > psDBF->nRecords )
-        return( FALSE );
-
-    if( psDBF->bNoHeader )
+    if (psDBF->bNoHeader)
         DBFWriteHeader(psDBF);
 
-/* -------------------------------------------------------------------- */
-/*      Is this a brand new record?                                     */
-/* -------------------------------------------------------------------- */
-    if( hEntity == psDBF->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Is this a brand new record?                                     */
+    /* -------------------------------------------------------------------- */
+    if (hEntity == psDBF->nRecords)
     {
-       if( !DBFFlushRecord( psDBF ) )
+        if (!DBFFlushRecord(psDBF))
             return FALSE;
 
-       psDBF->nRecords++;
-       for( i = 0; i < psDBF->nRecordLength; i++ )
-           psDBF->pszCurrentRecord[i] = ' ';
+        psDBF->nRecords++;
+        for (int i = 0; i < psDBF->nRecordLength; i++)
+            psDBF->pszCurrentRecord[i] = ' ';
 
-       psDBF->nCurrentRecord = hEntity;
+        psDBF->nCurrentRecord = hEntity;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Is this an existing record, but different than the last one     */
-/*      we accessed?                                                    */
-/* -------------------------------------------------------------------- */
-    if( !DBFLoadRecord( psDBF, hEntity ) )
+    /* -------------------------------------------------------------------- */
+    /*      Is this an existing record, but different than the last one     */
+    /*      we accessed?                                                    */
+    /* -------------------------------------------------------------------- */
+    if (!DBFLoadRecord(psDBF, hEntity))
         return FALSE;
 
-    pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
+    unsigned char *pabyRec =
+        REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
 
-    memcpy ( pabyRec, pRawTuple,  psDBF->nRecordLength );
+    memcpy(pabyRec, pRawTuple, psDBF->nRecordLength);
 
     psDBF->bCurrentRecordModified = TRUE;
     psDBF->bUpdated = TRUE;
 
-    return( TRUE );
+    return (TRUE);
 }
 
 /************************************************************************/
@@ -1762,63 +1571,70 @@ DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
 /*      till the next record read for any reason.                       */
 /************************************************************************/
 
-const char SHPAPI_CALL1(*)
-DBFReadTuple(DBFHandle psDBF, int hEntity )
+const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity)
 
 {
-    if( hEntity < 0 || hEntity >= psDBF->nRecords )
+    if (hEntity < 0 || hEntity >= psDBF->nRecords)
         return SHPLIB_NULLPTR;
 
-    if( !DBFLoadRecord( psDBF, hEntity ) )
+    if (!DBFLoadRecord(psDBF, hEntity))
         return SHPLIB_NULLPTR;
 
     return STATIC_CAST(const char *, psDBF->pszCurrentRecord);
 }
 
 /************************************************************************/
-/*                          DBFCloneEmpty()                              */
+/*                          DBFCloneEmpty()                             */
 /*                                                                      */
 /*      Read one of the attribute fields of a record.                   */
 /************************************************************************/
 
-DBFHandle SHPAPI_CALL
-DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
+DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename)
 {
-    DBFHandle  newDBF;
-
-   newDBF = DBFCreateEx ( pszFilename, psDBF->pszCodePage );
-   if ( newDBF == SHPLIB_NULLPTR ) return SHPLIB_NULLPTR;
-
-   newDBF->nFields = psDBF->nFields;
-   newDBF->nRecordLength = psDBF->nRecordLength;
-   newDBF->nHeaderLength = psDBF->nHeaderLength;
-
-   if( psDBF->pszHeader )
-   {
-        newDBF->pszHeader = STATIC_CAST(char *, malloc ( XBASE_FLDHDR_SZ * psDBF->nFields ));
-        memcpy ( newDBF->pszHeader, psDBF->pszHeader, XBASE_FLDHDR_SZ * psDBF->nFields );
-   }
-
-   newDBF->panFieldOffset = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
-   memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
-   newDBF->panFieldSize = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
-   memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
-   newDBF->panFieldDecimals = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
-   memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
-   newDBF->pachFieldType = STATIC_CAST(char *, malloc ( sizeof(char) * psDBF->nFields ));
-   memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(char)*psDBF->nFields );
-
-   newDBF->bNoHeader = TRUE;
-   newDBF->bUpdated = TRUE;
-   newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+    DBFHandle newDBF = DBFCreateEx(pszFilename, psDBF->pszCodePage);
+    if (newDBF == SHPLIB_NULLPTR)
+        return SHPLIB_NULLPTR;
 
-   DBFWriteHeader ( newDBF );
-   DBFClose ( newDBF );
+    newDBF->nFields = psDBF->nFields;
+    newDBF->nRecordLength = psDBF->nRecordLength;
+    newDBF->nHeaderLength = psDBF->nHeaderLength;
 
-   newDBF = DBFOpen ( pszFilename, "rb+" );
-   newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+    if (psDBF->pszHeader)
+    {
+        newDBF->pszHeader =
+            STATIC_CAST(char *, malloc(XBASE_FLDHDR_SZ * psDBF->nFields));
+        memcpy(newDBF->pszHeader, psDBF->pszHeader,
+               XBASE_FLDHDR_SZ * psDBF->nFields);
+    }
 
-   return ( newDBF );
+    newDBF->panFieldOffset =
+        STATIC_CAST(int *, malloc(sizeof(int) * psDBF->nFields));
+    memcpy(newDBF->panFieldOffset, psDBF->panFieldOffset,
+           sizeof(int) * psDBF->nFields);
+    newDBF->panFieldSize =
+        STATIC_CAST(int *, malloc(sizeof(int) * psDBF->nFields));
+    memcpy(newDBF->panFieldSize, psDBF->panFieldSize,
+           sizeof(int) * psDBF->nFields);
+    newDBF->panFieldDecimals =
+        STATIC_CAST(int *, malloc(sizeof(int) * psDBF->nFields));
+    memcpy(newDBF->panFieldDecimals, psDBF->panFieldDecimals,
+           sizeof(int) * psDBF->nFields);
+    newDBF->pachFieldType =
+        STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nFields));
+    memcpy(newDBF->pachFieldType, psDBF->pachFieldType,
+           sizeof(char) * psDBF->nFields);
+
+    newDBF->bNoHeader = TRUE;
+    newDBF->bUpdated = TRUE;
+    newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+
+    DBFWriteHeader(newDBF);
+    DBFClose(newDBF);
+
+    newDBF = DBFOpen(pszFilename, "rb+");
+    newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+
+    return (newDBF);
 }
 
 /************************************************************************/
@@ -1832,14 +1648,13 @@ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
 /*                           'M' (Memo: 10 digits .DBT block ptr)       */
 /************************************************************************/
 
-char SHPAPI_CALL
-DBFGetNativeFieldType( DBFHandle psDBF, int iField )
+char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle psDBF, int iField)
 
 {
-    if( iField >=0 && iField < psDBF->nFields )
+    if (iField >= 0 && iField < psDBF->nFields)
         return psDBF->pachFieldType[iField];
 
-    return  ' ';
+    return ' ';
 }
 
 /************************************************************************/
@@ -1850,20 +1665,17 @@ DBFGetNativeFieldType( DBFHandle psDBF, int iField )
 /*      Contributed by Jim Matthews.                                    */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
-
+int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
 {
-    char          name[XBASE_FLDNAME_LEN_READ+1];
-    int           i;
+    char name[XBASE_FLDNAME_LEN_READ + 1];
 
-    for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
+    for (int i = 0; i < DBFGetFieldCount(psDBF); i++)
     {
-        DBFGetFieldInfo( psDBF, i, name, SHPLIB_NULLPTR, SHPLIB_NULLPTR );
-        if(!STRCASECMP(pszFieldName,name))
-            return(i);
+        DBFGetFieldInfo(psDBF, i, name, SHPLIB_NULLPTR, SHPLIB_NULLPTR);
+        if (!STRCASECMP(pszFieldName, name))
+            return (i);
     }
-    return(-1);
+    return (-1);
 }
 
 /************************************************************************/
@@ -1873,24 +1685,23 @@ DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
 /*      it returns FALSE.                                               */
 /************************************************************************/
 
-int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape )
-
+int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape)
 {
-/* -------------------------------------------------------------------- */
-/*      Verify selection.                                               */
-/* -------------------------------------------------------------------- */
-    if( iShape < 0 || iShape >= psDBF->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Verify selection.                                               */
+    /* -------------------------------------------------------------------- */
+    if (iShape < 0 || iShape >= psDBF->nRecords)
         return TRUE;
 
-/* -------------------------------------------------------------------- */
-/*     Have we read the record?                                        */
-/* -------------------------------------------------------------------- */
-    if( !DBFLoadRecord( psDBF, iShape ) )
+    /* -------------------------------------------------------------------- */
+    /*      Have we read the record?                                        */
+    /* -------------------------------------------------------------------- */
+    if (!DBFLoadRecord(psDBF, iShape))
         return FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      '*' means deleted.                                              */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      '*' means deleted.                                              */
+    /* -------------------------------------------------------------------- */
     return psDBF->pszCurrentRecord[0] == '*';
 }
 
@@ -1898,34 +1709,32 @@ int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape )
 /*                        DBFMarkRecordDeleted()                        */
 /************************************************************************/
 
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
-                                      int bIsDeleted )
-
+int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape,
+                                     int bIsDeleted)
 {
-    char chNewFlag;
-
-/* -------------------------------------------------------------------- */
-/*      Verify selection.                                               */
-/* -------------------------------------------------------------------- */
-    if( iShape < 0 || iShape >= psDBF->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Verify selection.                                               */
+    /* -------------------------------------------------------------------- */
+    if (iShape < 0 || iShape >= psDBF->nRecords)
         return FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      Is this an existing record, but different than the last one     */
-/*      we accessed?                                                    */
-/* -------------------------------------------------------------------- */
-    if( !DBFLoadRecord( psDBF, iShape ) )
+    /* -------------------------------------------------------------------- */
+    /*      Is this an existing record, but different than the last one     */
+    /*      we accessed?                                                    */
+    /* -------------------------------------------------------------------- */
+    if (!DBFLoadRecord(psDBF, iShape))
         return FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      Assign value, marking record as dirty if it changes.            */
-/* -------------------------------------------------------------------- */
-    if( bIsDeleted )
+    /* -------------------------------------------------------------------- */
+    /*      Assign value, marking record as dirty if it changes.            */
+    /* -------------------------------------------------------------------- */
+    char chNewFlag;
+    if (bIsDeleted)
         chNewFlag = '*';
     else
         chNewFlag = ' ';
 
-    if( psDBF->pszCurrentRecord[0] != chNewFlag )
+    if (psDBF->pszCurrentRecord[0] != chNewFlag)
     {
         psDBF->bCurrentRecordModified = TRUE;
         psDBF->bUpdated = TRUE;
@@ -1939,10 +1748,9 @@ int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
 /*                            DBFGetCodePage                            */
 /************************************************************************/
 
-const char SHPAPI_CALL1(*)
-DBFGetCodePage(DBFHandle psDBF )
+const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF)
 {
-    if( psDBF == SHPLIB_NULLPTR )
+    if (psDBF == SHPLIB_NULLPTR)
         return SHPLIB_NULLPTR;
     return psDBF->pszCodePage;
 }
@@ -1953,109 +1761,110 @@ DBFGetCodePage(DBFHandle psDBF )
 /*      Remove a field from a .dbf file                                 */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFDeleteField(DBFHandle psDBF, int iField)
+int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField)
 {
-    int nOldRecordLength, nOldHeaderLength;
-    int nDeletedFieldOffset, nDeletedFieldSize;
-    SAOffset nRecordOffset;
-    char* pszRecord;
-    int i, iRecord;
-
     if (iField < 0 || iField >= psDBF->nFields)
         return FALSE;
 
     /* make sure that everything is written in .dbf */
-    if( !DBFFlushRecord( psDBF ) )
+    if (!DBFFlushRecord(psDBF))
         return FALSE;
 
     /* get information about field to be deleted */
-    nOldRecordLength = psDBF->nRecordLength;
-    nOldHeaderLength = psDBF->nHeaderLength;
-    nDeletedFieldOffset = psDBF->panFieldOffset[iField];
-    nDeletedFieldSize = psDBF->panFieldSize[iField];
+    int nOldRecordLength = psDBF->nRecordLength;
+    int nOldHeaderLength = psDBF->nHeaderLength;
+    int nDeletedFieldOffset = psDBF->panFieldOffset[iField];
+    int nDeletedFieldSize = psDBF->panFieldSize[iField];
 
     /* update fields info */
-    for (i = iField + 1; i < psDBF->nFields; i++)
+    for (int i = iField + 1; i < psDBF->nFields; i++)
     {
-        psDBF->panFieldOffset[i-1] = psDBF->panFieldOffset[i] - nDeletedFieldSize;
-        psDBF->panFieldSize[i-1] = psDBF->panFieldSize[i];
-        psDBF->panFieldDecimals[i-1] = psDBF->panFieldDecimals[i];
-        psDBF->pachFieldType[i-1] = psDBF->pachFieldType[i];
+        psDBF->panFieldOffset[i - 1] =
+            psDBF->panFieldOffset[i] - nDeletedFieldSize;
+        psDBF->panFieldSize[i - 1] = psDBF->panFieldSize[i];
+        psDBF->panFieldDecimals[i - 1] = psDBF->panFieldDecimals[i];
+        psDBF->pachFieldType[i - 1] = psDBF->pachFieldType[i];
     }
 
     /* resize fields arrays */
     psDBF->nFields--;
 
-    psDBF->panFieldOffset = STATIC_CAST(int *,
-        SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ));
+    psDBF->panFieldOffset = STATIC_CAST(
+        int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));
 
-    psDBF->panFieldSize = STATIC_CAST(int *,
-        SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ));
+    psDBF->panFieldSize = STATIC_CAST(
+        int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));
 
-    psDBF->panFieldDecimals = STATIC_CAST(int *,
-        SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ));
+    psDBF->panFieldDecimals = STATIC_CAST(
+        int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));
 
-    psDBF->pachFieldType = STATIC_CAST(char *,
-        SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ));
+    psDBF->pachFieldType = STATIC_CAST(
+        char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));
 
     /* update header information */
     psDBF->nHeaderLength -= XBASE_FLDHDR_SZ;
     psDBF->nRecordLength -= nDeletedFieldSize;
 
     /* overwrite field information in header */
-    memmove(psDBF->pszHeader + iField*XBASE_FLDHDR_SZ,
-           psDBF->pszHeader + (iField+1)*XBASE_FLDHDR_SZ,
-           sizeof(char) * (psDBF->nFields - iField)*XBASE_FLDHDR_SZ);
+    memmove(psDBF->pszHeader + iField * XBASE_FLDHDR_SZ,
+            psDBF->pszHeader + (iField + 1) * XBASE_FLDHDR_SZ,
+            sizeof(char) * (psDBF->nFields - iField) * XBASE_FLDHDR_SZ);
 
-    psDBF->pszHeader = STATIC_CAST(char *, SfRealloc(psDBF->pszHeader,
-                                          psDBF->nFields*XBASE_FLDHDR_SZ));
+    psDBF->pszHeader = STATIC_CAST(
+        char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));
 
     /* update size of current record appropriately */
-    psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
-                                                 psDBF->nRecordLength));
+    psDBF->pszCurrentRecord = STATIC_CAST(
+        char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
 
     /* we're done if we're dealing with not yet created .dbf */
-    if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+    if (psDBF->bNoHeader && psDBF->nRecords == 0)
         return TRUE;
 
     /* force update of header with new header and record length */
     psDBF->bNoHeader = TRUE;
-    DBFUpdateHeader( psDBF );
+    DBFUpdateHeader(psDBF);
 
     /* alloc record */
-    pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
+    char *pszRecord =
+        STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
 
     /* shift records to their new positions */
-    for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+    for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
     {
-        nRecordOffset =
-            nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + nOldHeaderLength;
+        SAOffset nRecordOffset =
+            nOldRecordLength * STATIC_CAST(SAOffset, iRecord) +
+            nOldHeaderLength;
 
         /* load record */
-        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-        psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+        psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+        if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1, psDBF->fp) != 1)
+        {
+            free(pszRecord);
+            return FALSE;
+        }
 
-        nRecordOffset =
-            psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+        nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+                        psDBF->nHeaderLength;
 
         /* move record in two steps */
-        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-        psDBF->sHooks.FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->fp );
-        psDBF->sHooks.FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
-                              nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
-                              1, psDBF->fp );
-
+        psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+        psDBF->sHooks.FWrite(pszRecord, nDeletedFieldOffset, 1, psDBF->fp);
+        psDBF->sHooks.FWrite(
+            pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
+            nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize, 1,
+            psDBF->fp);
     }
 
-    if( psDBF->bWriteEndOfFileChar )
+    if (psDBF->bWriteEndOfFileChar)
     {
         char ch = END_OF_FILE_CHARACTER;
         SAOffset nEOFOffset =
-            psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+            psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+            psDBF->nHeaderLength;
 
-        psDBF->sHooks.FSeek( psDBF->fp, nEOFOffset, 0 );
-        psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+        psDBF->sHooks.FSeek(psDBF->fp, nEOFOffset, 0);
+        psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
     }
 
     /* TODO: truncate file */
@@ -2080,36 +1889,30 @@ DBFDeleteField(DBFHandle psDBF, int iField)
 /* code of DBFReorderFields.                                            */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFReorderFields( DBFHandle psDBF, int* panMap )
+int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
 {
-    SAOffset nRecordOffset;
-    int      i, iRecord;
-    int     *panFieldOffsetNew;
-    int     *panFieldSizeNew;
-    int     *panFieldDecimalsNew;
-    char    *pachFieldTypeNew;
-    char    *pszHeaderNew;
-    char    *pszRecord;
-    char    *pszRecordNew;
-
-    if ( psDBF->nFields == 0 )
+    if (psDBF->nFields == 0)
         return TRUE;
 
     /* make sure that everything is written in .dbf */
-    if( !DBFFlushRecord( psDBF ) )
+    if (!DBFFlushRecord(psDBF))
         return FALSE;
 
-    /* a simple malloc() would be enough, but calloc() helps clang static analyzer */
-    panFieldOffsetNew = STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
-    panFieldSizeNew = STATIC_CAST(int *, calloc(sizeof(int),  psDBF->nFields));
-    panFieldDecimalsNew = STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
-    pachFieldTypeNew = STATIC_CAST(char *, calloc(sizeof(char), psDBF->nFields));
-    pszHeaderNew = STATIC_CAST(char*, malloc(sizeof(char) * XBASE_FLDHDR_SZ * 
-                                  psDBF->nFields));
+    /* a simple malloc() would be enough, but calloc() helps clang static
+     * analyzer */
+    int *panFieldOffsetNew =
+        STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+    int *panFieldSizeNew =
+        STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+    int *panFieldDecimalsNew =
+        STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+    char *pachFieldTypeNew =
+        STATIC_CAST(char *, calloc(sizeof(char), psDBF->nFields));
+    char *pszHeaderNew = STATIC_CAST(
+        char *, malloc(sizeof(char) * XBASE_FLDHDR_SZ * psDBF->nFields));
 
     /* shuffle fields definitions */
-    for(i=0; i < psDBF->nFields; i++)
+    for (int i = 0; i < psDBF->nFields; i++)
     {
         panFieldSizeNew[i] = psDBF->panFieldSize[panMap[i]];
         panFieldDecimalsNew[i] = psDBF->panFieldDecimals[panMap[i]];
@@ -2118,38 +1921,49 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
                psDBF->pszHeader + panMap[i] * XBASE_FLDHDR_SZ, XBASE_FLDHDR_SZ);
     }
     panFieldOffsetNew[0] = 1;
-    for(i=1; i < psDBF->nFields; i++)
+    for (int i = 1; i < psDBF->nFields; i++)
     {
-        panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
+        panFieldOffsetNew[i] =
+            panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
     }
 
     free(psDBF->pszHeader);
     psDBF->pszHeader = pszHeaderNew;
 
+    bool errorAbort = false;
+
     /* we're done if we're dealing with not yet created .dbf */
-    if ( !(psDBF->bNoHeader && psDBF->nRecords == 0) )
+    if (!(psDBF->bNoHeader && psDBF->nRecords == 0))
     {
         /* force update of header with new header and record length */
         psDBF->bNoHeader = TRUE;
-        DBFUpdateHeader( psDBF );
+        DBFUpdateHeader(psDBF);
 
         /* alloc record */
-        pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-        pszRecordNew = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+        char *pszRecord =
+            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+        char *pszRecordNew =
+            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
 
         /* shuffle fields in records */
-        for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+        for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
         {
-            nRecordOffset =
-                psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+            const SAOffset nRecordOffset =
+                psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+                psDBF->nHeaderLength;
 
             /* load record */
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FRead( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            if (psDBF->sHooks.FRead(pszRecord, psDBF->nRecordLength, 1,
+                                    psDBF->fp) != 1)
+            {
+                errorAbort = true;
+                break;
+            }
 
             pszRecordNew[0] = pszRecord[0];
 
-            for(i=0; i < psDBF->nFields; i++)
+            for (int i = 0; i < psDBF->nFields; i++)
             {
                 memcpy(pszRecordNew + panFieldOffsetNew[i],
                        pszRecord + psDBF->panFieldOffset[panMap[i]],
@@ -2157,8 +1971,9 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
             }
 
             /* write record */
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FWrite( pszRecordNew, psDBF->nRecordLength, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            psDBF->sHooks.FWrite(pszRecordNew, psDBF->nRecordLength, 1,
+                                 psDBF->fp);
         }
 
         /* free record */
@@ -2166,6 +1981,18 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
         free(pszRecordNew);
     }
 
+    if (errorAbort)
+    {
+        free(panFieldOffsetNew);
+        free(panFieldSizeNew);
+        free(panFieldDecimalsNew);
+        free(pachFieldTypeNew);
+        psDBF->nCurrentRecord = -1;
+        psDBF->bCurrentRecordModified = FALSE;
+        psDBF->bUpdated = FALSE;
+        return FALSE;
+    }
+
     free(psDBF->panFieldOffset);
     free(psDBF->panFieldSize);
     free(psDBF->panFieldDecimals);
@@ -2173,7 +2000,7 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
 
     psDBF->panFieldOffset = panFieldOffsetNew;
     psDBF->panFieldSize = panFieldSizeNew;
-    psDBF->panFieldDecimals =panFieldDecimalsNew;
+    psDBF->panFieldDecimals = panFieldDecimalsNew;
     psDBF->pachFieldType = pachFieldTypeNew;
 
     psDBF->nCurrentRecord = -1;
@@ -2183,71 +2010,59 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                          DBFAlterFieldDefn()                         */
 /*                                                                      */
 /*      Alter a field definition in a .dbf file                         */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
-                    char chType, int nWidth, int nDecimals )
+int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
+                                  const char *pszFieldName, char chType,
+                                  int nWidth, int nDecimals)
 {
-    int   i;
-    int   iRecord;
-    int   nOffset;
-    int   nOldWidth;
-    int   nOldRecordLength;
-    SAOffset  nRecordOffset;
-    char* pszFInfo;
-    char  chOldType;
-    int   bIsNULL;
-    char chFieldFill;
-
     if (iField < 0 || iField >= psDBF->nFields)
         return FALSE;
 
     /* make sure that everything is written in .dbf */
-    if( !DBFFlushRecord( psDBF ) )
+    if (!DBFFlushRecord(psDBF))
         return FALSE;
 
-    chFieldFill = DBFGetNullCharacter(chType);
+    const char chFieldFill = DBFGetNullCharacter(chType);
 
-    chOldType = psDBF->pachFieldType[iField];
-    nOffset = psDBF->panFieldOffset[iField];
-    nOldWidth = psDBF->panFieldSize[iField];
-    nOldRecordLength = psDBF->nRecordLength;
+    const char chOldType = psDBF->pachFieldType[iField];
+    const int nOffset = psDBF->panFieldOffset[iField];
+    const int nOldWidth = psDBF->panFieldSize[iField];
+    const int nOldRecordLength = psDBF->nRecordLength;
 
-/* -------------------------------------------------------------------- */
-/*      Do some checking to ensure we can add records to this file.     */
-/* -------------------------------------------------------------------- */
-    if( nWidth < 1 )
+    /* -------------------------------------------------------------------- */
+    /*      Do some checking to ensure we can add records to this file.     */
+    /* -------------------------------------------------------------------- */
+    if (nWidth < 1)
         return -1;
 
-    if( nWidth > XBASE_FLD_MAX_WIDTH )
+    if (nWidth > XBASE_FLD_MAX_WIDTH)
         nWidth = XBASE_FLD_MAX_WIDTH;
 
-/* -------------------------------------------------------------------- */
-/*      Assign the new field information fields.                        */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      Assign the new field information fields.                        */
+    /* -------------------------------------------------------------------- */
     psDBF->panFieldSize[iField] = nWidth;
     psDBF->panFieldDecimals[iField] = nDecimals;
     psDBF->pachFieldType[iField] = chType;
 
-/* -------------------------------------------------------------------- */
-/*      Update the header information.                                  */
-/* -------------------------------------------------------------------- */
-    pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * iField;
+    /* -------------------------------------------------------------------- */
+    /*      Update the header information.                                  */
+    /* -------------------------------------------------------------------- */
+    char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * iField;
 
-    for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
+    for (int i = 0; i < XBASE_FLDHDR_SZ; i++)
         pszFInfo[i] = '\0';
 
-    strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
+    strncpy(pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE);
 
     pszFInfo[11] = psDBF->pachFieldType[iField];
 
-    if( chType == 'C' )
+    if (chType == 'C')
     {
         pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
         pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
@@ -2258,60 +2073,71 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
         pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Update offsets                                                  */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      Update offsets                                                  */
+    /* -------------------------------------------------------------------- */
     if (nWidth != nOldWidth)
     {
-        for (i = iField + 1; i < psDBF->nFields; i++)
-             psDBF->panFieldOffset[i] += nWidth - nOldWidth;
+        for (int i = iField + 1; i < psDBF->nFields; i++)
+            psDBF->panFieldOffset[i] += nWidth - nOldWidth;
         psDBF->nRecordLength += nWidth - nOldWidth;
 
-        psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
-                                                     psDBF->nRecordLength));
+        psDBF->pszCurrentRecord = STATIC_CAST(
+            char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
     }
 
     /* we're done if we're dealing with not yet created .dbf */
-    if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+    if (psDBF->bNoHeader && psDBF->nRecords == 0)
         return TRUE;
 
     /* force update of header with new header and record length */
     psDBF->bNoHeader = TRUE;
-    DBFUpdateHeader( psDBF );
+    DBFUpdateHeader(psDBF);
+
+    bool errorAbort = false;
 
     if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
     {
-        char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
-        char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
+        char *pszRecord =
+            STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
+        char *pszOldField =
+            STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
 
         /* cppcheck-suppress uninitdata */
         pszOldField[nOldWidth] = 0;
 
         /* move records to their new positions */
-        for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+        for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
         {
-            nRecordOffset =
-                nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+            SAOffset nRecordOffset =
+                nOldRecordLength * STATIC_CAST(SAOffset, iRecord) +
+                psDBF->nHeaderLength;
 
             /* load record */
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1,
+                                    psDBF->fp) != 1)
+            {
+                errorAbort = true;
+                break;
+            }
 
             memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
-            bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+            const bool bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
 
             if (nWidth != nOldWidth)
             {
-                if ((chOldType == 'N' || chOldType == 'F' || chOldType == 'D') && pszOldField[0] == ' ')
+                if ((chOldType == 'N' || chOldType == 'F' ||
+                     chOldType == 'D') &&
+                    pszOldField[0] == ' ')
                 {
                     /* Strip leading spaces when truncating a numeric field */
-                    memmove( pszRecord + nOffset,
-                            pszRecord + nOffset + nOldWidth - nWidth,
-                            nWidth );
+                    memmove(pszRecord + nOffset,
+                            pszRecord + nOffset + nOldWidth - nWidth, nWidth);
                 }
                 if (nOffset + nOldWidth < nOldRecordLength)
                 {
-                    memmove( pszRecord + nOffset + nWidth,
+                    memmove(pszRecord + nOffset + nWidth,
                             pszRecord + nOffset + nOldWidth,
                             nOldRecordLength - (nOffset + nOldWidth));
                 }
@@ -2320,26 +2146,28 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
             /* Convert null value to the appropriate value of the new type */
             if (bIsNULL)
             {
-                memset( pszRecord + nOffset, chFieldFill, nWidth);
+                memset(pszRecord + nOffset, chFieldFill, nWidth);
             }
 
             nRecordOffset =
-                psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+                psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+                psDBF->nHeaderLength;
 
             /* write record */
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
         }
 
-        if( psDBF->bWriteEndOfFileChar )
+        if (!errorAbort && psDBF->bWriteEndOfFileChar)
         {
             char ch = END_OF_FILE_CHARACTER;
 
-            nRecordOffset =
-                psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+            SAOffset nRecordOffset =
+                psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+                psDBF->nHeaderLength;
 
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
         }
         /* TODO: truncate file */
 
@@ -2348,76 +2176,95 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
     }
     else if (nWidth > nOldWidth)
     {
-        char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
-        char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
+        char *pszRecord =
+            STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+        char *pszOldField =
+            STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
 
         /* cppcheck-suppress uninitdata */
         pszOldField[nOldWidth] = 0;
 
         /* move records to their new positions */
-        for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
+        for (int iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
         {
-            nRecordOffset =
-                nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+            SAOffset nRecordOffset =
+                nOldRecordLength * STATIC_CAST(SAOffset, iRecord) +
+                psDBF->nHeaderLength;
 
             /* load record */
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1,
+                                    psDBF->fp) != 1)
+            {
+                errorAbort = true;
+                break;
+            }
 
             memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
-            bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+            const bool bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
 
             if (nOffset + nOldWidth < nOldRecordLength)
             {
-                memmove( pszRecord + nOffset + nWidth,
-                         pszRecord + nOffset + nOldWidth,
-                         nOldRecordLength - (nOffset + nOldWidth));
+                memmove(pszRecord + nOffset + nWidth,
+                        pszRecord + nOffset + nOldWidth,
+                        nOldRecordLength - (nOffset + nOldWidth));
             }
 
             /* Convert null value to the appropriate value of the new type */
             if (bIsNULL)
             {
-                memset( pszRecord + nOffset, chFieldFill, nWidth);
+                memset(pszRecord + nOffset, chFieldFill, nWidth);
             }
             else
             {
                 if ((chOldType == 'N' || chOldType == 'F'))
                 {
                     /* Add leading spaces when expanding a numeric field */
-                    memmove( pszRecord + nOffset + nWidth - nOldWidth,
-                             pszRecord + nOffset, nOldWidth );
-                    memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
+                    memmove(pszRecord + nOffset + nWidth - nOldWidth,
+                            pszRecord + nOffset, nOldWidth);
+                    memset(pszRecord + nOffset, ' ', nWidth - nOldWidth);
                 }
                 else
                 {
                     /* Add trailing spaces */
-                    memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
+                    memset(pszRecord + nOffset + nOldWidth, ' ',
+                           nWidth - nOldWidth);
                 }
             }
 
             nRecordOffset =
-                psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+                psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+                psDBF->nHeaderLength;
 
             /* write record */
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
         }
 
-        if( psDBF->bWriteEndOfFileChar )
+        if (!errorAbort && psDBF->bWriteEndOfFileChar)
         {
             char ch = END_OF_FILE_CHARACTER;
 
-            nRecordOffset =
-                psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+            SAOffset nRecordOffset =
+                psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+                psDBF->nHeaderLength;
 
-            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
-            psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+            psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+            psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
         }
 
         free(pszRecord);
         free(pszOldField);
     }
 
+    if (errorAbort)
+    {
+        psDBF->nCurrentRecord = -1;
+        psDBF->bCurrentRecordModified = TRUE;
+        psDBF->bUpdated = FALSE;
+
+        return FALSE;
+    }
     psDBF->nCurrentRecord = -1;
     psDBF->bCurrentRecordModified = FALSE;
     psDBF->bUpdated = TRUE;
@@ -2429,7 +2276,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
 /*                    DBFSetWriteEndOfFileChar()                        */
 /************************************************************************/
 
-void SHPAPI_CALL DBFSetWriteEndOfFileChar( DBFHandle psDBF, int bWriteFlag )
+void SHPAPI_CALL DBFSetWriteEndOfFileChar(DBFHandle psDBF, int bWriteFlag)
 {
     psDBF->bWriteEndOfFileChar = bWriteFlag;
 }
index d2c7f581c5a954eff5dd68fff5635851fb88bf5e..b63a3933a7bddbd50e072d827a2b6ed1ba1d96d5 100644 (file)
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Default implementation of file io based on stdio.
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam
  *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING).  This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
  ******************************************************************************
  *
- * $Log: safileio.c,v $
- * Revision 1.6  2018-06-15 19:56:32  erouault
- * * safileio.c: remove duplicate test. Patch by Jaroslav Fojtik.
- * Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2744
- *
- * Revision 1.5  2016-12-05 12:44:05  erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.4  2008-01-16 20:05:14  bram
- * Add file hooks that accept UTF-8 encoded filenames on some platforms.  Use SASetupUtf8Hooks
- *  tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability.  Currently, this
- *  is only available on the Windows platform that decodes the UTF-8 filenames to wide
- *  character strings and feeds them to _wfopen and _wremove.
- *
- * Revision 1.3  2007/12/18 18:28:11  bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.2  2007/12/15 20:25:30  bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function.  This is 
- * either the number from the LDID header field ("LDID/<number>") or as the 
- * content of an accompanying .CPG file.  When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.1  2007/12/06 06:56:41  fwarmerdam
- * new
- *
  */
 
 #include "shapefil.h"
 
+#include <assert.h>
 #include <math.h>
 #include <limits.h>
-#include <assert.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
-
-SHP_CVSID("$Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $");
 
 #ifdef SHPAPI_UTF8_HOOKS
-#   ifdef SHPAPI_WINDOWS
-#       define WIN32_LEAN_AND_MEAN
-#       define NOMINMAX
-#       include <windows.h>
-#       pragma comment(lib, "kernel32.lib")
-#   endif
+#ifdef SHPAPI_WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <windows.h>
+#pragma comment(lib, "kernel32.lib")
+#endif
 #endif
 
-/************************************************************************/
-/*                              SADFOpen()                              */
-/************************************************************************/
-
-SAFile SADFOpen( const char *pszFilename, const char *pszAccess )
-
+static SAFile SADFOpen(const char *pszFilename, const char *pszAccess,
+                       void *pvUserData)
 {
-    return (SAFile) fopen( pszFilename, pszAccess );
+    (void)pvUserData;
+    return (SAFile)fopen(pszFilename, pszAccess);
 }
 
-/************************************************************************/
-/*                              SADFRead()                              */
-/************************************************************************/
-
-SAOffset SADFRead( void *p, SAOffset size, SAOffset nmemb, SAFile file )
-
+static SAOffset SADFRead(void *p, SAOffset size, SAOffset nmemb, SAFile file)
 {
-    return (SAOffset) fread( p, (size_t) size, (size_t) nmemb, 
-                             (FILE *) file );
+    return (SAOffset)fread(p, (size_t)size, (size_t)nmemb, (FILE *)file);
 }
 
-/************************************************************************/
-/*                             SADFWrite()                              */
-/************************************************************************/
-
-SAOffset SADFWrite( void *p, SAOffset size, SAOffset nmemb, SAFile file )
-
+static SAOffset SADFWrite(const void *p, SAOffset size, SAOffset nmemb,
+                          SAFile file)
 {
-    return (SAOffset) fwrite( p, (size_t) size, (size_t) nmemb, 
-                              (FILE *) file );
+    return (SAOffset)fwrite(p, (size_t)size, (size_t)nmemb, (FILE *)file);
 }
 
-/************************************************************************/
-/*                              SADFSeek()                              */
-/************************************************************************/
-
-SAOffset SADFSeek( SAFile file, SAOffset offset, int whence )
-
+static SAOffset SADFSeek(SAFile file, SAOffset offset, int whence)
 {
-    return (SAOffset) fseek( (FILE *) file, (long) offset, whence );
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+    return (SAOffset)_fseeki64((FILE *)file, (__int64)offset, whence);
+#else
+    return (SAOffset)fseek((FILE *)file, (long)offset, whence);
+#endif
 }
 
-/************************************************************************/
-/*                              SADFTell()                              */
-/************************************************************************/
-
-SAOffset SADFTell( SAFile file )
-
+static SAOffset SADFTell(SAFile file)
 {
-    return (SAOffset) ftell( (FILE *) file );
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+    return (SAOffset)_ftelli64((FILE *)file);
+#else
+    return (SAOffset)ftell((FILE *)file);
+#endif
 }
 
-/************************************************************************/
-/*                             SADFFlush()                              */
-/************************************************************************/
-
-int SADFFlush( SAFile file )
-
+static int SADFFlush(SAFile file)
 {
-    return fflush( (FILE *) file );
+    return fflush((FILE *)file);
 }
 
-/************************************************************************/
-/*                             SADFClose()                              */
-/************************************************************************/
-
-int SADFClose( SAFile file )
-
+static int SADFClose(SAFile file)
 {
-    return fclose( (FILE *) file );
+    return fclose((FILE *)file);
 }
 
-/************************************************************************/
-/*                             SADFClose()                              */
-/************************************************************************/
-
-int SADRemove( const char *filename )
-
+static int SADRemove(const char *filename, void *pvUserData)
 {
-    return remove( filename );
+    (void)pvUserData;
+    return remove(filename);
 }
 
-/************************************************************************/
-/*                              SADError()                              */
-/************************************************************************/
-
-void SADError( const char *message )
-
+static void SADError(const char *message)
 {
-    fprintf( stderr, "%s\n", message );
+    fprintf(stderr, "%s\n", message);
 }
 
-/************************************************************************/
-/*                        SASetupDefaultHooks()                         */
-/************************************************************************/
-
-void SASetupDefaultHooks( SAHooks *psHooks )
-
+void SASetupDefaultHooks(SAHooks *psHooks)
 {
-    psHooks->FOpen   = SADFOpen;
-    psHooks->FRead   = SADFRead;
-    psHooks->FWrite  = SADFWrite;
-    psHooks->FSeek   = SADFSeek;
-    psHooks->FTell   = SADFTell;
-    psHooks->FFlush  = SADFFlush;
-    psHooks->FClose  = SADFClose;
-    psHooks->Remove  = SADRemove;
-
-    psHooks->Error   = SADError;
-    psHooks->Atof    = atof;
+    psHooks->FOpen = SADFOpen;
+    psHooks->FRead = SADFRead;
+    psHooks->FWrite = SADFWrite;
+    psHooks->FSeek = SADFSeek;
+    psHooks->FTell = SADFTell;
+    psHooks->FFlush = SADFFlush;
+    psHooks->FClose = SADFClose;
+    psHooks->Remove = SADRemove;
+
+    psHooks->Error = SADError;
+    psHooks->Atof = atof;
+    psHooks->pvUserData = NULL;
 }
 
-
-
-
 #ifdef SHPAPI_WINDOWS
 
-/************************************************************************/
-/*                          Utf8ToWideChar                              */
-/************************************************************************/
-
-const wchar_t* Utf8ToWideChar( const char *pszFilename )
+static wchar_t *Utf8ToWideChar(const char *pszFilename)
 {
-    int nMulti, nWide;
-    wchar_t *pwszFileName;
-    
-    nMulti = strlen(pszFilename) + 1;
-    nWide = MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, 0, 0);
-    if( nWide == 0 )
+    const int nMulti = (int)strlen(pszFilename) + 1;
+    const int nWide =
+        MultiByteToWideChar(CP_UTF8, 0, pszFilename, nMulti, 0, 0);
+    if (nWide == 0)
     {
         return NULL;
     }
-    pwszFileName = (wchar_t*) malloc(nWide * sizeof(wchar_t));
-    if ( pwszFileName == NULL )
+    wchar_t *pwszFileName = (wchar_t *)malloc(nWide * sizeof(wchar_t));
+    if (pwszFileName == NULL)
     {
         return NULL;
     }
-    if( MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, pwszFileName, nWide ) == 0 )
+    if (MultiByteToWideChar(CP_UTF8, 0, pszFilename, nMulti, pwszFileName,
+                            nWide) == 0)
     {
-        free( pwszFileName );
+        free(pwszFileName);
         return NULL;
     }
     return pwszFileName;
@@ -234,62 +132,51 @@ const wchar_t* Utf8ToWideChar( const char *pszFilename )
 /*                           SAUtf8WFOpen                               */
 /************************************************************************/
 
-SAFile SAUtf8WFOpen( const char *pszFilename, const char *pszAccess )
+SAFile SAUtf8WFOpen(const char *pszFilename, const char *pszAccess)
 {
     SAFile file = NULL;
-    const wchar_t *pwszFileName, *pwszAccess;
-    pwszFileName = Utf8ToWideChar( pszFilename );
-    pwszAccess = Utf8ToWideChar( pszAccess );
-    if( pwszFileName != NULL && pwszAccess != NULL)
+    wchar_t *pwszFileName = Utf8ToWideChar(pszFilename);
+    wchar_t *pwszAccess = Utf8ToWideChar(pszAccess);
+    if (pwszFileName != NULL && pwszAccess != NULL)
     {
-        file = (SAFile) _wfopen( pwszFileName, pwszAccess );
+        file = (SAFile)_wfopen(pwszFileName, pwszAccess);
     }
-    free ((wchar_t*) pwszFileName);
-    free ((wchar_t*) pwszAccess);
+    free(pwszFileName);
+    free(pwszAccess);
     return file;
 }
 
-/************************************************************************/
-/*                             SAUtf8WRemove()                          */
-/************************************************************************/
-
-int SAUtf8WRemove( const char *pszFilename )
+int SAUtf8WRemove(const char *pszFilename)
 {
-    const wchar_t *pwszFileName = Utf8ToWideChar( pszFilename );
-    int rc = -1; 
-    if( pwszFileName != NULL )
+    wchar_t *pwszFileName = Utf8ToWideChar(pszFilename);
+    int rc = -1;
+    if (pwszFileName != NULL)
     {
-        rc = _wremove( pwszFileName );
+        rc = _wremove(pwszFileName);
     }
-    free ((wchar_t*) pwszFileName);
+    free(pwszFileName);
     return rc;
 }
 
 #endif
 
 #ifdef SHPAPI_UTF8_HOOKS
-
-/************************************************************************/
-/*                          SASetupUtf8Hooks()                          */
-/************************************************************************/
-
-void SASetupUtf8Hooks( SAHooks *psHooks )
-{
-#ifdef SHPAPI_WINDOWS    
-    psHooks->FOpen   = SAUtf8WFOpen;
-    psHooks->Remove  = SAUtf8WRemove;
-#else
-#   error "no implementations of UTF-8 hooks available for this platform"
+#ifndef SHPAPI_WINDOWS
+#error "no implementations of UTF-8 hooks available for this platform"
 #endif
-    psHooks->FRead   = SADFRead;
-    psHooks->FWrite  = SADFWrite;
-    psHooks->FSeek   = SADFSeek;
-    psHooks->FTell   = SADFTell;
-    psHooks->FFlush  = SADFFlush;
-    psHooks->FClose  = SADFClose;
 
-    psHooks->Error   = SADError;
-    psHooks->Atof    = atof;
+void SASetupUtf8Hooks(SAHooks *psHooks)
+{
+    psHooks->FOpen = SAUtf8WFOpen;
+    psHooks->Remove = SAUtf8WRemove;
+    psHooks->FRead = SADFRead;
+    psHooks->FWrite = SADFWrite;
+    psHooks->FSeek = SADFSeek;
+    psHooks->FTell = SADFTell;
+    psHooks->FFlush = SADFFlush;
+    psHooks->FClose = SADFClose;
+
+    psHooks->Error = SADError;
+    psHooks->Atof = atof;
 }
-
 #endif
index 199964d428ede7bf041ec1beb243a1f77fef152f..2328f15cc117b30b8608f51fb6b4b821c16459ef 100644 (file)
@@ -2,7 +2,6 @@
 #define SHAPEFILE_H_INCLUDED
 
 /******************************************************************************
- * $Id: shapefil.h,v 1.56 2018-08-16 15:39:07 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Primary include file for Shapelib.
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2012-2016, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2016, Even Rouault <even dot rouault at spatialys.com>
  *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING).  This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
  ******************************************************************************
  *
- * $Log: shapefil.h,v $
- * Revision 1.56  2018-08-16 15:39:07  erouault
- * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
- * internal shapelib. Mostly to allow building those files as C++
- * without warning. Also add FTDate entry in DBFFieldType
- * (see https://github.com/OSGeo/gdal/pull/308). And some other
- * code cleanups
- *
- * Revision 1.55  2016-12-05 18:44:08  erouault
- * * dbfopen.c, shapefil.h: write DBF end-of-file character 0x1A by default.
- * This behaviour can be controlled with the DBFSetWriteEndOfFileChar()
- * function.
- *
- * Revision 1.54  2016-12-05 12:44:05  erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.53  2016-12-04 15:30:15  erouault
- * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
- * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
- * structures extended with new members. New functions:
- * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
- * SHPSetFastModeReadObject
- *
- * * sbnsearch.c: new file to implement original ESRI .sbn spatial
- * index reading. (no write support). New functions:
- * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
- * SBNSearchDiskTreeInteger, SBNSearchFreeIds
- *
- * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
- * with new file and symbols.
- *
- * * commit: helper script to cvs commit
- *
- * Revision 1.52  2011-12-11 22:26:46  fwarmerdam
- * upgrade .qix access code to use SAHooks (gdal #3365)
- *
- * Revision 1.51  2011-07-24 05:59:25  fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.50  2011-05-13 17:35:17  fwarmerdam
- * added DBFReorderFields() and DBFAlterFields() functions (from Even)
- *
- * Revision 1.49  2011-04-16 14:38:21  fwarmerdam
- * avoid warnings with gcc on SHP_CVSID
- *
- * Revision 1.48  2010-08-27 23:42:52  fwarmerdam
- * add SHPAPI_CALL attribute in code
- *
- * Revision 1.47  2010-01-28 11:34:34  fwarmerdam
- * handle the shape file length limits more gracefully (#3236)
- *
- * Revision 1.46  2008-11-12 14:28:15  fwarmerdam
- * DBFCreateField() now works on files with records
- *
- * Revision 1.45  2008/11/11 17:47:10  fwarmerdam
- * added DBFDeleteField() function
- *
- * Revision 1.44  2008/01/16 20:05:19  bram
- * Add file hooks that accept UTF-8 encoded filenames on some platforms.  Use SASetupUtf8Hooks
- *  tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability.  Currently, this
- *  is only available on the Windows platform that decodes the UTF-8 filenames to wide
- *  character strings and feeds them to _wfopen and _wremove.
- *
- * Revision 1.43  2008/01/10 16:35:30  fwarmerdam
- * avoid _ prefix on #defined symbols (bug 1840)
- *
- * Revision 1.42  2007/12/18 18:28:14  bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.41  2007/12/15 20:25:32  bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function.  This is 
- * either the number from the LDID header field ("LDID/<number>") or as the 
- * content of an accompanying .CPG file.  When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.40  2007/12/06 07:00:25  fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.39  2007/12/04 20:37:56  fwarmerdam
- * preliminary implementation of hooks api for io and errors
- *
- * Revision 1.38  2007/11/21 22:39:56  fwarmerdam
- * close shx file in readonly mode (GDAL #1956)
- *
- * Revision 1.37  2007/10/27 03:31:14  fwarmerdam
- * limit default depth of tree to 12 levels (gdal ticket #1594)
- *
- * Revision 1.36  2007/09/10 23:33:15  fwarmerdam
- * Upstreamed support for visibility flag in SHPAPI_CALL for the needs
- * of GDAL (gdal ticket #1810).
- *
- * Revision 1.35  2007/09/03 19:48:10  fwarmerdam
- * move DBFReadAttribute() static dDoubleField into dbfinfo
- *
- * Revision 1.34  2006/06/17 15:33:32  fwarmerdam
- * added pszWorkField - bug 1202 (rso)
- *
- * Revision 1.33  2006/02/15 01:14:30  fwarmerdam
- * added DBFAddNativeFieldType
- *
- * Revision 1.32  2006/01/26 15:07:32  fwarmerdam
- * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
- *
- * Revision 1.31  2006/01/05 01:27:27  fwarmerdam
- * added dbf deletion mark/fetch
- *
- * Revision 1.30  2005/01/03 22:30:13  fwarmerdam
- * added support for saved quadtrees
- *
- * Revision 1.29  2004/09/26 20:09:35  fwarmerdam
- * avoid rcsid warnings
- *
- * Revision 1.28  2003/12/29 06:02:18  fwarmerdam
- * added cpl_error.h option
- *
- * Revision 1.27  2003/04/21 18:30:37  warmerda
- * added header write/update public methods
- *
- * Revision 1.26  2002/09/29 00:00:08  warmerda
- * added FTLogical and logical attribute read/write calls
- *
- * Revision 1.25  2002/05/07 13:46:30  warmerda
- * added DBFWriteAttributeDirectly().
- *
- * Revision 1.24  2002/04/10 16:59:54  warmerda
- * added SHPRewindObject
- *
- * Revision 1.23  2002/01/15 14:36:07  warmerda
- * updated email address
- *
- * Revision 1.22  2002/01/15 14:32:00  warmerda
- * try to improve SHPAPI_CALL docs
  */
 
 #include <stdio.h>
 
-#ifdef USE_DBMALLOC
-#include <dbmalloc.h>
-#endif
-
 #ifdef USE_CPL
 #include "cpl_conv.h"
 #endif
 
 #ifdef __cplusplus
-extern "C" {
+extern "C"
+{
 #endif
 
+/************************************************************************/
+/*           Version related macros (added in 1.6.0)                    */
+/************************************************************************/
+
+#define SHAPELIB_VERSION_MAJOR 1
+#define SHAPELIB_VERSION_MINOR 6
+#define SHAPELIB_VERSION_MICRO 0
+
+#define SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro) \
+    ((major) * 10000 + (minor) * 100 + (micro))
+
+#define SHAPELIB_VERSION_NUMBER \
+    SHAPELIB_MAKE_VERSION_NUMBER(SHAPELIB_VERSION_MAJOR, SHAPELIB_VERSION_MINOR, SHAPELIB_VERSION_MICRO)
+
+#define SHAPELIB_AT_LEAST(major, minor, micro) \
+    (SHAPELIB_VERSION_NUMBER >= SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro))
+
 /************************************************************************/
 /*                        Configuration options.                        */
 /************************************************************************/
@@ -206,66 +61,51 @@ extern "C" {
 /* -------------------------------------------------------------------- */
 #define DISABLE_MULTIPATCH_MEASURE
 
-/* -------------------------------------------------------------------- */
-/*      SHPAPI_CALL                                                     */
-/*                                                                      */
-/*      The following two macros are present to allow forcing           */
-/*      various calling conventions on the Shapelib API.                */
-/*                                                                      */
-/*      To force __stdcall conventions (needed to call Shapelib         */
-/*      from Visual Basic and/or Dephi I believe) the makefile could    */
-/*      be modified to define:                                          */
-/*                                                                      */
-/*        /DSHPAPI_CALL=__stdcall                                       */
-/*                                                                      */
-/*      If it is desired to force export of the Shapelib API without    */
-/*      using the shapelib.def file, use the following definition.      */
-/*                                                                      */
-/*        /DSHAPELIB_DLLEXPORT                                          */
-/*                                                                      */
-/*      To get both at once it will be necessary to hack this           */
-/*      include file to define:                                         */
-/*                                                                      */
-/*        #define SHPAPI_CALL __declspec(dllexport) __stdcall           */
-/*        #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall        */
-/*                                                                      */
-/*      The complexity of the situation is partly caused by the        */
-/*      peculiar requirement of Visual C++ that __stdcall appear        */
-/*      after any "*"'s in the return value of a function while the     */
-/*      __declspec(dllexport) must appear before them.                  */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      SHPAPI_CALL                                                     */
+    /*                                                                      */
+    /*      The following two macros are present to allow forcing           */
+    /*      various calling conventions on the Shapelib API.                */
+    /*                                                                      */
+    /*      To force __stdcall conventions (needed to call Shapelib         */
+    /*      from Visual Basic and/or Delphi I believe) the makefile could   */
+    /*      be modified to define:                                          */
+    /*                                                                      */
+    /*        /DSHPAPI_CALL=__stdcall                                       */
+    /*                                                                      */
+    /*      If it is desired to force export of the Shapelib API without    */
+    /*      using the shapelib.def file, use the following definition.      */
+    /*                                                                      */
+    /*        /DSHAPELIB_DLLEXPORT                                          */
+    /*                                                                      */
+    /*      To get both at once it will be necessary to hack this           */
+    /*      include file to define:                                         */
+    /*                                                                      */
+    /*        #define SHPAPI_CALL __declspec(dllexport) __stdcall           */
+    /*        #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall        */
+    /*                                                                      */
+    /*      The complexity of the situation is partly caused by the        */
+    /*      peculiar requirement of Visual C++ that __stdcall appear        */
+    /*      after any "*"'s in the return value of a function while the     */
+    /*      __declspec(dllexport) must appear before them.                  */
+    /* -------------------------------------------------------------------- */
 
 #ifdef SHAPELIB_DLLEXPORT
-#  define SHPAPI_CALL __declspec(dllexport)
-#  define SHPAPI_CALL1(x)  __declspec(dllexport) x
+#define SHPAPI_CALL __declspec(dllexport)
+#define SHPAPI_CALL1(x) __declspec(dllexport) x
 #endif
 
 #ifndef SHPAPI_CALL
-#  if defined(USE_GCC_VISIBILITY_FLAG)
-#    define SHPAPI_CALL     __attribute__ ((visibility("default")))
-#    define SHPAPI_CALL1(x) __attribute__ ((visibility("default")))     x
-#  else
-#    define SHPAPI_CALL
-#  endif
+#if defined(USE_GCC_VISIBILITY_FLAG)
+#define SHPAPI_CALL __attribute__((visibility("default")))
+#define SHPAPI_CALL1(x) __attribute__((visibility("default"))) x
+#else
+#define SHPAPI_CALL
 #endif
-
-#ifndef SHPAPI_CALL1
-#  define SHPAPI_CALL1(x)      x SHPAPI_CALL
 #endif
 
-/* -------------------------------------------------------------------- */
-/*      Macros for controlling CVSID and ensuring they don't appear     */
-/*      as unreferenced variables resulting in lots of warnings.        */
-/* -------------------------------------------------------------------- */
-#ifndef DISABLE_CVSID
-#  if defined(__GNUC__) && __GNUC__ >= 4
-#    define SHP_CVSID(string)     static const char cpl_cvsid[] __attribute__((used)) = string;
-#  else
-#    define SHP_CVSID(string)     static const char cpl_cvsid[] = string; \
-static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
-#  endif
-#else
-#  define SHP_CVSID(string)
+#ifndef SHPAPI_CALL1
+#define SHPAPI_CALL1(x) x SHPAPI_CALL
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -273,204 +113,201 @@ static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
 /*      UTF-8 encoded filenames Unicode filenames                       */
 /* -------------------------------------------------------------------- */
 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-#  define SHPAPI_WINDOWS
-#  define SHPAPI_UTF8_HOOKS
+#define SHPAPI_WINDOWS
+#define SHPAPI_UTF8_HOOKS
 #endif
 
-/* -------------------------------------------------------------------- */
-/*      IO/Error hook functions.                                        */
-/* -------------------------------------------------------------------- */
-typedef int *SAFile;
+    /* -------------------------------------------------------------------- */
+    /*      IO/Error hook functions.                                        */
+    /* -------------------------------------------------------------------- */
+    typedef int *SAFile;
 
 #ifndef SAOffset
-typedef unsigned long SAOffset;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+    typedef unsigned __int64 SAOffset;
+#else
+    typedef unsigned long SAOffset;
+#endif
 #endif
 
-typedef struct {
-    SAFile     (*FOpen) ( const char *filename, const char *access);
-    SAOffset   (*FRead) ( void *p, SAOffset size, SAOffset nmemb, SAFile file);
-    SAOffset   (*FWrite)( void *p, SAOffset size, SAOffset nmemb, SAFile file);
-    SAOffset   (*FSeek) ( SAFile file, SAOffset offset, int whence );
-    SAOffset   (*FTell) ( SAFile file );
-    int        (*FFlush)( SAFile file );
-    int        (*FClose)( SAFile file );
-    int        (*Remove) ( const char *filename );
-
-    void       (*Error) ( const char *message );
-    double     (*Atof)  ( const char *str );
-} SAHooks;
-
-void SHPAPI_CALL SASetupDefaultHooks( SAHooks *psHooks );
+    typedef struct
+    {
+        SAFile (*FOpen)(const char *filename, const char *access,
+                        void *pvUserData);
+        SAOffset (*FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file);
+        SAOffset (*FWrite)(const void *p, SAOffset size, SAOffset nmemb,
+                           SAFile file);
+        SAOffset (*FSeek)(SAFile file, SAOffset offset, int whence);
+        SAOffset (*FTell)(SAFile file);
+        int (*FFlush)(SAFile file);
+        int (*FClose)(SAFile file);
+        int (*Remove)(const char *filename, void *pvUserData);
+
+        void (*Error)(const char *message);
+        double (*Atof)(const char *str);
+        void *pvUserData;
+    } SAHooks;
+
+    void SHPAPI_CALL SASetupDefaultHooks(SAHooks *psHooks);
 #ifdef SHPAPI_UTF8_HOOKS
-void SHPAPI_CALL SASetupUtf8Hooks( SAHooks *psHooks );
+    void SHPAPI_CALL SASetupUtf8Hooks(SAHooks *psHooks);
 #endif
 
-/************************************************************************/
-/*                             SHP Support.                             */
-/************************************************************************/
-typedef struct tagSHPObject SHPObject;
+    /************************************************************************/
+    /*                             SHP Support.                             */
+    /************************************************************************/
+    typedef struct tagSHPObject SHPObject;
 
-typedef struct
-{
-    SAHooks sHooks;
+    typedef struct
+    {
+        SAHooks sHooks;
 
-    SAFile      fpSHP;
-    SAFile      fpSHX;
+        SAFile fpSHP;
+        SAFile fpSHX;
 
-    int         nShapeType;  /* SHPT_* */
+        int nShapeType; /* SHPT_* */
 
-    unsigned int nFileSize;  /* SHP file */
+        unsigned int nFileSize; /* SHP file */
 
-    int         nRecords;
-    int         nMaxRecords;
-    unsigned int*panRecOffset;
-    unsigned int *panRecSize;
+        int nRecords;
+        int nMaxRecords;
+        unsigned int *panRecOffset;
+        unsigned int *panRecSize;
 
-    double      adBoundsMin[4];
-    double      adBoundsMax[4];
+        double adBoundsMin[4];
+        double adBoundsMax[4];
 
-    int         bUpdated;
+        int bUpdated;
 
-    unsigned char *pabyRec;
-    int         nBufSize;
+        unsigned char *pabyRec;
+        int nBufSize;
 
-    int            bFastModeReadObject;
-    unsigned char *pabyObjectBuf;
-    int            nObjectBufSize;
-    SHPObject*     psCachedObject;
-} SHPInfo;
+        int bFastModeReadObject;
+        unsigned char *pabyObjectBuf;
+        int nObjectBufSize;
+        SHPObject *psCachedObject;
+    } SHPInfo;
 
-typedef SHPInfo * SHPHandle;
+    typedef SHPInfo *SHPHandle;
 
 /* -------------------------------------------------------------------- */
 /*      Shape types (nSHPType)                                          */
 /* -------------------------------------------------------------------- */
-#define SHPT_NULL       0
-#define SHPT_POINT      1
-#define SHPT_ARC        3
-#define SHPT_POLYGON    5
+#define SHPT_NULL 0
+#define SHPT_POINT 1
+#define SHPT_ARC 3
+#define SHPT_POLYGON 5
 #define SHPT_MULTIPOINT 8
-#define SHPT_POINTZ     11
-#define SHPT_ARCZ       13
-#define SHPT_POLYGONZ   15
+#define SHPT_POINTZ 11
+#define SHPT_ARCZ 13
+#define SHPT_POLYGONZ 15
 #define SHPT_MULTIPOINTZ 18
-#define SHPT_POINTM     21
-#define SHPT_ARCM       23
-#define SHPT_POLYGONM   25
+#define SHPT_POINTM 21
+#define SHPT_ARCM 23
+#define SHPT_POLYGONM 25
 #define SHPT_MULTIPOINTM 28
 #define SHPT_MULTIPATCH 31
 
-/* -------------------------------------------------------------------- */
-/*      Part types - everything but SHPT_MULTIPATCH just uses           */
-/*      SHPP_RING.                                                      */
-/* -------------------------------------------------------------------- */
-
-#define SHPP_TRISTRIP   0
-#define SHPP_TRIFAN     1
-#define SHPP_OUTERRING  2
-#define SHPP_INNERRING  3
-#define SHPP_FIRSTRING  4
-#define SHPP_RING       5
-
-/* -------------------------------------------------------------------- */
-/*      SHPObject - represents on shape (without attributes) read       */
-/*      from the .shp file.                                             */
-/* -------------------------------------------------------------------- */
-struct tagSHPObject
-{
-    int    nSHPType;
-
-    int    nShapeId;  /* -1 is unknown/unassigned */
-
-    int    nParts;
-    int    *panPartStart;
-    int    *panPartType;
-
-    int    nVertices;
-    double *padfX;
-    double *padfY;
-    double *padfZ;
-    double *padfM;
-
-    double dfXMin;
-    double dfYMin;
-    double dfZMin;
-    double dfMMin;
-
-    double dfXMax;
-    double dfYMax;
-    double dfZMax;
-    double dfMMax;
-
-    int    bMeasureIsUsed;
-    int    bFastModeReadObject;
-};
-
-/* -------------------------------------------------------------------- */
-/*      SHP API Prototypes                                              */
-/* -------------------------------------------------------------------- */
-
-/* If pszAccess is read-only, the fpSHX field of the returned structure */
-/* will be NULL as it is not necessary to keep the SHX file open */
-SHPHandle SHPAPI_CALL
-      SHPOpen( const char * pszShapeFile, const char * pszAccess );
-SHPHandle SHPAPI_CALL
-      SHPOpenLL( const char *pszShapeFile, const char *pszAccess,
-                 SAHooks *psHooks );
-SHPHandle SHPAPI_CALL
-      SHPOpenLLEx( const char *pszShapeFile, const char *pszAccess,
-                  SAHooks *psHooks, int bRestoreSHX );
-
-int SHPAPI_CALL
-      SHPRestoreSHX( const char *pszShapeFile, const char *pszAccess,
-                  SAHooks *psHooks );
-
-/* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the SHPHandle. */
-/* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
-/* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
-/* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
-void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode );
-
-SHPHandle SHPAPI_CALL
-      SHPCreate( const char * pszShapeFile, int nShapeType );
-SHPHandle SHPAPI_CALL
-      SHPCreateLL( const char * pszShapeFile, int nShapeType,
-                   SAHooks *psHooks );
-void SHPAPI_CALL
-      SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
-                  double * padfMinBound, double * padfMaxBound );
-
-SHPObject SHPAPI_CALL1(*)
-      SHPReadObject( SHPHandle hSHP, int iShape );
-int SHPAPI_CALL
-      SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
-
-void SHPAPI_CALL
-      SHPDestroyObject( SHPObject * psObject );
-void SHPAPI_CALL
-      SHPComputeExtents( SHPObject * psObject );
-SHPObject SHPAPI_CALL1(*)
-      SHPCreateObject( int nSHPType, int nShapeId, int nParts,
-                       const int * panPartStart, const int * panPartType,
-                       int nVertices,
-                       const double * padfX, const double * padfY,
-                       const double * padfZ, const double * padfM );
-SHPObject SHPAPI_CALL1(*)
-      SHPCreateSimpleObject( int nSHPType, int nVertices,
-                             const double * padfX,
-                             const double * padfY,
-                             const double * padfZ );
-
-int SHPAPI_CALL
-      SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
-
-void SHPAPI_CALL SHPClose( SHPHandle hSHP );
-void SHPAPI_CALL SHPWriteHeader( SHPHandle hSHP );
-
-const char SHPAPI_CALL1(*)
-      SHPTypeName( int nSHPType );
-const char SHPAPI_CALL1(*)
-      SHPPartTypeName( int nPartType );
+    /* -------------------------------------------------------------------- */
+    /*      Part types - everything but SHPT_MULTIPATCH just uses           */
+    /*      SHPP_RING.                                                      */
+    /* -------------------------------------------------------------------- */
+
+#define SHPP_TRISTRIP 0
+#define SHPP_TRIFAN 1
+#define SHPP_OUTERRING 2
+#define SHPP_INNERRING 3
+#define SHPP_FIRSTRING 4
+#define SHPP_RING 5
+
+    /* -------------------------------------------------------------------- */
+    /*      SHPObject - represents on shape (without attributes) read       */
+    /*      from the .shp file.                                             */
+    /* -------------------------------------------------------------------- */
+    struct tagSHPObject
+    {
+        int nSHPType;
+
+        int nShapeId; /* -1 is unknown/unassigned */
+
+        int nParts;
+        int *panPartStart;
+        int *panPartType;
+
+        int nVertices;
+        double *padfX;
+        double *padfY;
+        double *padfZ;
+        double *padfM;
+
+        double dfXMin;
+        double dfYMin;
+        double dfZMin;
+        double dfMMin;
+
+        double dfXMax;
+        double dfYMax;
+        double dfZMax;
+        double dfMMax;
+
+        int bMeasureIsUsed;
+        int bFastModeReadObject;
+    };
+
+    /* -------------------------------------------------------------------- */
+    /*      SHP API Prototypes                                              */
+    /* -------------------------------------------------------------------- */
+
+    /* If pszAccess is read-only, the fpSHX field of the returned structure */
+    /* will be NULL as it is not necessary to keep the SHX file open */
+    SHPHandle SHPAPI_CALL SHPOpen(const char *pszShapeFile,
+                                  const char *pszAccess);
+    SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszShapeFile,
+                                    const char *pszAccess,
+                                    const SAHooks *psHooks);
+    SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszShapeFile,
+                                      const char *pszAccess,
+                                      const SAHooks *psHooks, int bRestoreSHX);
+
+    int SHPAPI_CALL SHPRestoreSHX(const char *pszShapeFile,
+                                  const char *pszAccess,
+                                  const SAHooks *psHooks);
+
+    /* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the SHPHandle. */
+    /* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
+    /* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
+    /* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
+    void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode);
+
+    SHPHandle SHPAPI_CALL SHPCreate(const char *pszShapeFile, int nShapeType);
+    SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszShapeFile, int nShapeType,
+                                      const SAHooks *psHooks);
+    void SHPAPI_CALL SHPGetInfo(SHPHandle hSHP, int *pnEntities,
+                                int *pnShapeType, double *padfMinBound,
+                                double *padfMaxBound);
+
+    SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle hSHP, int iShape);
+    int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape,
+                                   SHPObject *psObject);
+
+    void SHPAPI_CALL SHPDestroyObject(SHPObject *psObject);
+    void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject);
+    SHPObject SHPAPI_CALL1(*)
+        SHPCreateObject(int nSHPType, int nShapeId, int nParts,
+                        const int *panPartStart, const int *panPartType,
+                        int nVertices, const double *padfX, const double *padfY,
+                        const double *padfZ, const double *padfM);
+    SHPObject SHPAPI_CALL1(*)
+        SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX,
+                              const double *padfY, const double *padfZ);
+
+    int SHPAPI_CALL SHPRewindObject(SHPHandle hSHP, SHPObject *psObject);
+
+    void SHPAPI_CALL SHPClose(SHPHandle hSHP);
+    void SHPAPI_CALL SHPWriteHeader(SHPHandle hSHP);
+
+    const char SHPAPI_CALL1(*) SHPTypeName(int nSHPType);
+    const char SHPAPI_CALL1(*) SHPPartTypeName(int nPartType);
 
 /* -------------------------------------------------------------------- */
 /*      Shape quadtree indexing API.                                    */
@@ -482,271 +319,244 @@ const char SHPAPI_CALL1(*)
 /* upper limit of tree levels for automatic estimation */
 #define MAX_DEFAULT_TREE_DEPTH 12
 
-typedef struct shape_tree_node
-{
-    /* region covered by this node */
-    double      adfBoundsMin[4];
-    double      adfBoundsMax[4];
+    typedef struct shape_tree_node
+    {
+        /* region covered by this node */
+        double adfBoundsMin[4];
+        double adfBoundsMax[4];
 
-    /* list of shapes stored at this node.  The papsShapeObj pointers
-       or the whole list can be NULL */
-    int         nShapeCount;
-    int         *panShapeIds;
-    SHPObject   **papsShapeObj;
+        /* list of shapes stored at this node.  The papsShapeObj pointers
+           or the whole list can be NULL */
+        int nShapeCount;
+        int *panShapeIds;
+        SHPObject **papsShapeObj;
 
-    int         nSubNodes;
-    struct shape_tree_node *apsSubNode[MAX_SUBNODE];
+        int nSubNodes;
+        struct shape_tree_node *apsSubNode[MAX_SUBNODE];
 
-} SHPTreeNode;
+    } SHPTreeNode;
 
-typedef struct
-{
-    SHPHandle   hSHP;
+    typedef struct
+    {
+        SHPHandle hSHP;
 
-    int         nMaxDepth;
-    int         nDimension;
-    int         nTotalCount;
+        int nMaxDepth;
+        int nDimension;
+        int nTotalCount;
 
-    SHPTreeNode *psRoot;
-} SHPTree;
+        SHPTreeNode *psRoot;
+    } SHPTree;
 
-SHPTree SHPAPI_CALL1(*)
-      SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
-                     double *padfBoundsMin, double *padfBoundsMax );
-void SHPAPI_CALL
-      SHPDestroyTree( SHPTree * hTree );
+    SHPTree SHPAPI_CALL1(*)
+        SHPCreateTree(SHPHandle hSHP, int nDimension, int nMaxDepth,
+                      const double *padfBoundsMin, const double *padfBoundsMax);
+    void SHPAPI_CALL SHPDestroyTree(SHPTree *hTree);
 
-int SHPAPI_CALL
-      SHPWriteTree( SHPTree *hTree, const char * pszFilename );
+    int SHPAPI_CALL SHPWriteTree(SHPTree *hTree, const char *pszFilename);
 
-int SHPAPI_CALL
-      SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
-int SHPAPI_CALL
-      SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
+    int SHPAPI_CALL SHPTreeAddShapeId(SHPTree *hTree, SHPObject *psObject);
+    int SHPAPI_CALL SHPTreeRemoveShapeId(SHPTree *hTree, int nShapeId);
 
-void SHPAPI_CALL
-      SHPTreeTrimExtraNodes( SHPTree * hTree );
+    void SHPAPI_CALL SHPTreeTrimExtraNodes(SHPTree *hTree);
 
-int SHPAPI_CALL1(*)
-      SHPTreeFindLikelyShapes( SHPTree * hTree,
-                               double * padfBoundsMin,
-                               double * padfBoundsMax,
-                               int * );
-int SHPAPI_CALL
-      SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+    int SHPAPI_CALL1(*)
+        SHPTreeFindLikelyShapes(SHPTree *hTree, double *padfBoundsMin,
+                                double *padfBoundsMax, int *);
+    int SHPAPI_CALL SHPCheckBoundsOverlap(const double *, const double *,
+                                          const double *, const double *, int);
 
-int SHPAPI_CALL1(*)
-SHPSearchDiskTree( FILE *fp,
-                   double *padfBoundsMin, double *padfBoundsMax,
-                   int *pnShapeCount );
+    int SHPAPI_CALL1(*)
+        SHPSearchDiskTree(FILE *fp, double *padfBoundsMin,
+                          double *padfBoundsMax, int *pnShapeCount);
 
-typedef struct SHPDiskTreeInfo* SHPTreeDiskHandle;
+    typedef struct SHPDiskTreeInfo *SHPTreeDiskHandle;
 
-SHPTreeDiskHandle SHPAPI_CALL
-    SHPOpenDiskTree( const char* pszQIXFilename,
-                     SAHooks *psHooks );
+    SHPTreeDiskHandle SHPAPI_CALL SHPOpenDiskTree(const char *pszQIXFilename,
+                                                  const SAHooks *psHooks);
 
-void SHPAPI_CALL
-    SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree );
+    void SHPAPI_CALL SHPCloseDiskTree(SHPTreeDiskHandle hDiskTree);
 
-int SHPAPI_CALL1(*)
-SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
-                     double *padfBoundsMin, double *padfBoundsMax,
-                     int *pnShapeCount );
+    int SHPAPI_CALL1(*)
+        SHPSearchDiskTreeEx(SHPTreeDiskHandle hDiskTree, double *padfBoundsMin,
+                            double *padfBoundsMax, int *pnShapeCount);
 
-int SHPAPI_CALL
-    SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename, SAHooks *psHooks );
+    int SHPAPI_CALL SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename,
+                                   const SAHooks *psHooks);
 
-/* -------------------------------------------------------------------- */
-/*      SBN Search API                                                  */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      SBN Search API                                                  */
+    /* -------------------------------------------------------------------- */
 
-typedef struct SBNSearchInfo* SBNSearchHandle;
+    typedef struct SBNSearchInfo *SBNSearchHandle;
 
-SBNSearchHandle SHPAPI_CALL
-    SBNOpenDiskTree( const char* pszSBNFilename,
-                 SAHooks *psHooks );
+    SBNSearchHandle SHPAPI_CALL SBNOpenDiskTree(const char *pszSBNFilename,
+                                                const SAHooks *psHooks);
 
-void SHPAPI_CALL
-    SBNCloseDiskTree( SBNSearchHandle hSBN );
+    void SHPAPI_CALL SBNCloseDiskTree(SBNSearchHandle hSBN);
 
-int SHPAPI_CALL1(*)
-SBNSearchDiskTree( SBNSearchHandle hSBN,
-                   double *padfBoundsMin, double *padfBoundsMax,
-                   int *pnShapeCount );
+    int SHPAPI_CALL1(*)
+        SBNSearchDiskTree(SBNSearchHandle hSBN, const double *padfBoundsMin,
+                          const double *padfBoundsMax, int *pnShapeCount);
 
-int SHPAPI_CALL1(*)
-SBNSearchDiskTreeInteger( SBNSearchHandle hSBN,
-                          int bMinX, int bMinY, int bMaxX, int bMaxY,
-                          int *pnShapeCount );
+    int SHPAPI_CALL1(*)
+        SBNSearchDiskTreeInteger(SBNSearchHandle hSBN, int bMinX, int bMinY,
+                                 int bMaxX, int bMaxY, int *pnShapeCount);
 
-void SHPAPI_CALL SBNSearchFreeIds( int* panShapeId );
+    void SHPAPI_CALL SBNSearchFreeIds(int *panShapeId);
 
-/************************************************************************/
-/*                             DBF Support.                             */
-/************************************************************************/
-typedef struct
-{
-    SAHooks sHooks;
+    /************************************************************************/
+    /*                             DBF Support.                             */
+    /************************************************************************/
+    typedef struct
+    {
+        SAHooks sHooks;
 
-    SAFile      fp;
+        SAFile fp;
 
-    int         nRecords;
+        int nRecords;
 
-    int         nRecordLength; /* Must fit on uint16 */
-    int         nHeaderLength; /* File header length (32) + field
-                                  descriptor length + spare space.
-                                  Must fit on uint16 */
-    int         nFields;
-    int         *panFieldOffset;
-    int         *panFieldSize;
-    int         *panFieldDecimals;
-    char        *pachFieldType;
+        int nRecordLength; /* Must fit on uint16 */
+        int nHeaderLength; /* File header length (32) + field
+                              descriptor length + spare space.
+                              Must fit on uint16 */
+        int nFields;
+        int *panFieldOffset;
+        int *panFieldSize;
+        int *panFieldDecimals;
+        char *pachFieldType;
 
-    char        *pszHeader; /* Field descriptors */
+        char *pszHeader; /* Field descriptors */
 
-    int         nCurrentRecord;
-    int         bCurrentRecordModified;
-    char        *pszCurrentRecord;
+        int nCurrentRecord;
+        int bCurrentRecordModified;
+        char *pszCurrentRecord;
 
-    int         nWorkFieldLength;
-    char        *pszWorkField;
+        int nWorkFieldLength;
+        char *pszWorkField;
 
-    int         bNoHeader;
-    int         bUpdated;
+        int bNoHeader;
+        int bUpdated;
 
-    union
-    {
-        double      dfDoubleField;
-        int         nIntField;
-    } fieldValue;
+        union
+        {
+            double dfDoubleField;
+            int nIntField;
+        } fieldValue;
+
+        int iLanguageDriver;
+        char *pszCodePage;
 
-    int         iLanguageDriver;
-    char        *pszCodePage;
+        int nUpdateYearSince1900; /* 0-255 */
+        int nUpdateMonth;         /* 1-12 */
+        int nUpdateDay;           /* 1-31 */
 
-    int         nUpdateYearSince1900; /* 0-255 */
-    int         nUpdateMonth; /* 1-12 */
-    int         nUpdateDay; /* 1-31 */
+        int bWriteEndOfFileChar; /* defaults to TRUE */
 
-    int         bWriteEndOfFileChar; /* defaults to TRUE */
-} DBFInfo;
+        int bRequireNextWriteSeek;
+    } DBFInfo;
 
-typedef DBFInfo * DBFHandle;
+    typedef DBFInfo *DBFHandle;
 
-typedef enum {
-  FTString,
-  FTInteger,
-  FTDouble,
-  FTLogical,
-  FTDate,
-  FTInvalid
-} DBFFieldType;
+    typedef enum
+    {
+        FTString,
+        FTInteger,
+        FTDouble,
+        FTLogical,
+        FTDate,
+        FTInvalid
+    } DBFFieldType;
 
 /* Field descriptor/header size */
-#define XBASE_FLDHDR_SZ         32
+#define XBASE_FLDHDR_SZ 32
 /* Shapelib read up to 11 characters, even if only 10 should normally be used */
-#define XBASE_FLDNAME_LEN_READ  11
+#define XBASE_FLDNAME_LEN_READ 11
 /* On writing, we limit to 10 characters */
 #define XBASE_FLDNAME_LEN_WRITE 10
 /* Normally only 254 characters should be used. We tolerate 255 historically */
-#define XBASE_FLD_MAX_WIDTH     255
-
-DBFHandle SHPAPI_CALL
-      DBFOpen( const char * pszDBFFile, const char * pszAccess );
-DBFHandle SHPAPI_CALL
-      DBFOpenLL( const char * pszDBFFile, const char * pszAccess,
-                 SAHooks *psHooks );
-DBFHandle SHPAPI_CALL
-      DBFCreate( const char * pszDBFFile );
-DBFHandle SHPAPI_CALL
-      DBFCreateEx( const char * pszDBFFile, const char * pszCodePage );
-DBFHandle SHPAPI_CALL
-      DBFCreateLL( const char * pszDBFFile, const char * pszCodePage, SAHooks *psHooks );
-
-int SHPAPI_CALL
-      DBFGetFieldCount( DBFHandle psDBF );
-int SHPAPI_CALL
-      DBFGetRecordCount( DBFHandle psDBF );
-int SHPAPI_CALL
-      DBFAddField( DBFHandle hDBF, const char * pszFieldName,
-                   DBFFieldType eType, int nWidth, int nDecimals );
-
-int SHPAPI_CALL
-      DBFAddNativeFieldType( DBFHandle hDBF, const char * pszFieldName,
-                             char chType, int nWidth, int nDecimals );
-
-int SHPAPI_CALL
-      DBFDeleteField( DBFHandle hDBF, int iField );
-
-int SHPAPI_CALL
-      DBFReorderFields( DBFHandle psDBF, int* panMap );
-
-int SHPAPI_CALL
-      DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
-                         char chType, int nWidth, int nDecimals );
-
-DBFFieldType SHPAPI_CALL
-      DBFGetFieldInfo( DBFHandle psDBF, int iField,
-                       char * pszFieldName, int * pnWidth, int * pnDecimals );
-
-int SHPAPI_CALL
-      DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
-
-int SHPAPI_CALL
-      DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-double SHPAPI_CALL
-      DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
-const char SHPAPI_CALL1(*)
-      DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
-const char SHPAPI_CALL1(*)
-      DBFReadLogicalAttribute( DBFHandle hDBF, int iShape, int iField );
-int SHPAPI_CALL
-      DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
-
-int SHPAPI_CALL
-      DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
-                                int nFieldValue );
-int SHPAPI_CALL
-      DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
-                               double dFieldValue );
-int SHPAPI_CALL
-      DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
-                               const char * pszFieldValue );
-int SHPAPI_CALL
-     DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
-
-int SHPAPI_CALL
-     DBFWriteLogicalAttribute( DBFHandle hDBF, int iShape, int iField,
-                               const char lFieldValue);
-int SHPAPI_CALL
-     DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
-                               void * pValue );
-const char SHPAPI_CALL1(*)
-      DBFReadTuple(DBFHandle psDBF, int hEntity );
-int SHPAPI_CALL
-      DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
-
-int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape );
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
-                                      int bIsDeleted );
-
-DBFHandle SHPAPI_CALL
-      DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
-
-void SHPAPI_CALL
-      DBFClose( DBFHandle hDBF );
-void    SHPAPI_CALL
-      DBFUpdateHeader( DBFHandle hDBF );
-char SHPAPI_CALL
-      DBFGetNativeFieldType( DBFHandle hDBF, int iField );
-
-const char SHPAPI_CALL1(*)
-      DBFGetCodePage(DBFHandle psDBF );
-
-void SHPAPI_CALL
-    DBFSetLastModifiedDate( DBFHandle psDBF, int nYYSince1900, int nMM, int nDD );
-
-void SHPAPI_CALL DBFSetWriteEndOfFileChar( DBFHandle psDBF, int bWriteFlag );
+#define XBASE_FLD_MAX_WIDTH 255
+
+    DBFHandle SHPAPI_CALL DBFOpen(const char *pszDBFFile,
+                                  const char *pszAccess);
+    DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszDBFFile,
+                                    const char *pszAccess,
+                                    const SAHooks *psHooks);
+    DBFHandle SHPAPI_CALL DBFCreate(const char *pszDBFFile);
+    DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszDBFFile,
+                                      const char *pszCodePage);
+    DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszDBFFile,
+                                      const char *pszCodePage,
+                                      const SAHooks *psHooks);
+
+    int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF);
+    int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF);
+    int SHPAPI_CALL DBFAddField(DBFHandle hDBF, const char *pszFieldName,
+                                DBFFieldType eType, int nWidth, int nDecimals);
+
+    int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle hDBF,
+                                          const char *pszFieldName, char chType,
+                                          int nWidth, int nDecimals);
+
+    int SHPAPI_CALL DBFDeleteField(DBFHandle hDBF, int iField);
+
+    int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap);
+
+    int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
+                                      const char *pszFieldName, char chType,
+                                      int nWidth, int nDecimals);
+
+    DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField,
+                                             char *pszFieldName, int *pnWidth,
+                                             int *pnDecimals);
+
+    int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+
+    int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle hDBF, int iShape,
+                                            int iField);
+    double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle hDBF, int iShape,
+                                              int iField);
+    const char SHPAPI_CALL1(*)
+        DBFReadStringAttribute(DBFHandle hDBF, int iShape, int iField);
+    const char SHPAPI_CALL1(*)
+        DBFReadLogicalAttribute(DBFHandle hDBF, int iShape, int iField);
+    int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle hDBF, int iShape, int iField);
+
+    int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle hDBF, int iShape,
+                                             int iField, int nFieldValue);
+    int SHPAPI_CALL DBFWriteDoubleAttribute(DBFHandle hDBF, int iShape,
+                                            int iField, double dFieldValue);
+    int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle hDBF, int iShape,
+                                            int iField,
+                                            const char *pszFieldValue);
+    int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle hDBF, int iShape,
+                                          int iField);
+
+    int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle hDBF, int iShape,
+                                             int iField,
+                                             const char lFieldValue);
+    int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity,
+                                              int iField, const void *pValue);
+    const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity);
+    int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity,
+                                  const void *pRawTuple);
+
+    int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape);
+    int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape,
+                                         int bIsDeleted);
+
+    DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF,
+                                        const char *pszFilename);
+
+    void SHPAPI_CALL DBFClose(DBFHandle hDBF);
+    void SHPAPI_CALL DBFUpdateHeader(DBFHandle hDBF);
+    char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle hDBF, int iField);
+
+    const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF);
+
+    void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900,
+                                            int nMM, int nDD);
+
+    void SHPAPI_CALL DBFSetWriteEndOfFileChar(DBFHandle psDBF, int bWriteFlag);
 
 #ifdef __cplusplus
 }
index fa81f91aa6aefdf76b0b945aaf3b54146c10a368..b3d72ba5a049cfd1f0e07d8241d61e77f1cd1352 100644 (file)
@@ -27,20 +27,19 @@ and the associated attribute file (.dbf).<p>
 <h2>What is a Shapefile?</h2>
 
 If you don't know, you probably don't need this library.  The Shapefile
-format is a working and interchange format promulagated by 
+format is a working and interchange format promulgated by
 <a href="http://www.esri.com/">ESRI</a> for simple vector data with attributes.
 <p>
 
-An excellent <a href="dl/shapefile.pdf">white paper</a> on the shapefile format 
-is available from ESRI,
-but it is .pdf format, so you will need Adobe Acrobat to browse it.<p>
+An excellent <a href="https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf">white paper</a>
+on the shapefile format is available from ESRI.<p>
 
 The file format actually consists of three files.<p>
 
 <pre>
 XXX.shp - holds the actual vertices.
 XXX.shx - hold index data pointing to the structures in the .shp file.
-XXX.dbf - holds the attributes in xBase (dBase) format.  
+XXX.dbf - holds the attributes in xBase (dBase) format.
 </pre>
 
 <h2>Download</h2>
@@ -48,27 +47,22 @@ XXX.dbf - holds the attributes in xBase (dBase) format.
 Source code, and some other odds and ends can be downloaded from
 <a href="http://download.osgeo.org/shapelib">http://download.osgeo.org/shapelib</a>.<p>
 
-Shapelib is available for anonymous CVS access:
-
-<pre>
-  cvs -d :pserver:cvsanon@cvs.maptools.org:/cvs/maptools/cvsroot login
-  Password: (hit enter)
-  cvs -d :pserver:cvsanon@cvs.maptools.org:/cvs/maptools/cvsroot co shapelib
-</pre>
+Shapelib repository is at
+<a href="https://github.com/OSGeo/shapelib">https://github.com/OSGeo/shapelib</a><p>
 
 <h2>Bugs, Maintainance and Support</h2>
 
-This library is maintained by <a href="http://pobox.com/~warmerdam">Frank 
-Warmerdam</a>.  Please send me bug reports, patches and suggestions for the 
+This library is maintained by <a href="http://pobox.com/~warmerdam">Frank
+Warmerdam</a>.  Please send me bug reports, patches and suggestions for the
 library via the <a href="http://bugzilla.maptools.org/enter_bug.cgi?product=Shapelib">maptools.org Bugzilla</a>.  Shapelib bugs can also be
 <a href="http://bugzilla.maptools.org/query.cgi?product=Shapelib">queried</a>.
 <p>
 
-Shapelib is hosted at 
+Shapelib is hosted at
 <a href="http://shapelib.maptools.org">shapelib.maptools.org</a>.   A mailing
-list for discussion of how to use shapelib, and announcing new releases 
-<a href="http://lists.maptools.org/mailman/listinfo/shapelib/">is 
-available</a>. To get notification of new releases of Shapelib <i>subscribe</i> to 
+list for discussion of how to use shapelib, and announcing new releases
+<a href="http://lists.maptools.org/mailman/listinfo/shapelib/">is
+available</a>. To get notification of new releases of Shapelib <i>subscribe</i> to
 the project mailing list at https://lists.osgeo.org/pipermail/shapelib/.<p>
 
 <h2>Credits</h2>
@@ -78,7 +72,7 @@ contributors to Shapelib are lost in pre-history.
 
 <ul>
 <li> Bill Miller (NY-DOT) for shputils.c
-<li> Carl Anderson for the contents of the contrib directory, and 
+<li> Carl Anderson for the contents of the contrib directory, and
 the "tuple" additions to dbfopen.c.
 <li> Andrea Giacomelli for patches for dbfopen.c.
 <li> Doug Matthews for portability improvements.
@@ -96,10 +90,10 @@ who hosted shapelib for years.
 <h2>In Memorium</h2>
 
 I would like to dedicate Shapelib to the memory of Sol Katz.  While I never
-met him in person, his generous contributions to the GIS community took 
+met him in person, his generous contributions to the GIS community took
 many forms, including free distribution of a variety of GIS translators
-with source.  The fact that he used this Shapelib in some of his utilities, 
-and thanked me was a great encouragement to me.  I hope I can do his memory 
+with source.  The fact that he used this Shapelib in some of his utilities,
+and thanked me was a great encouragement to me.  I hope I can do his memory
 honour by trying to contribute in a similar fashion.<p>
 
 <h2>Portability</h2>
@@ -114,7 +108,7 @@ such as MSDOS.<p>
 The shputils.c module is contributed, and may not take the same approach
 to portability as the rest of the package.<p>
 
-On Linux, and most unix systems it should be possible to build and 
+On Linux, and most unix systems it should be possible to build and
 install shapefile support as a shared library using the "lib" and "lib_install"
 targets of the Makefile.  Note that this Makefile doesn't use autoconf
 mechanisms and will generally require some hand tailoring for your environment.
@@ -123,11 +117,11 @@ mechanisms and will generally require some hand tailoring for your environment.
 
 <ul>
 
-<li> You can't modify the vertices of existing structures (though you 
-   can update the attributes of existing structures, and create new 
+<li> You can't modify the vertices of existing structures (though you
+   can update the attributes of existing structures, and create new
    structures).<p>
 
-<li> Not written in such a way as to be particularly fast.  This is 
+<li> Not written in such a way as to be particularly fast.  This is
 particularly true of the 1.2 API.  For applications more concerned with
 speed it may be worth using the V1.1 API.<p>
 
@@ -159,32 +153,32 @@ files through appropriate use of the DBF and SHP APIs.<p>
 
 <li> <a href="codepage.html">Language ID / Code Page mappings</a><p>
 
-<li> Shapelib is used within the multiformat 
-<a href="http://ogr.maptools.org/">OGR</a> library.  If you are looking for a 
+<li> Shapelib is used within the multiformat
+<a href="http://ogr.maptools.org/">OGR</a> library.  If you are looking for a
 high level C++ library with support for many geospatial vector formats you
 might want to check it out.<p>
 
-<li> Ari Jolma has produced an initial <b>perl</b> binding on top of shapelib, 
-which can be found at CPAN as Geo::ShapeFile under the 
+<li> Ari Jolma has produced an initial <b>perl</b> binding on top of shapelib,
+which can be found at CPAN as Geo::ShapeFile under the
 <a href="http://www.cpan.org/modules/by-module/Geo/">Geo</a> module.
 <p>
 
-<li> Bernhard Herzog has produced <b>python</b> bindings for Shapelib with 
-SWIG, available at <a href="http://ftp.intevation.de/users/bh/pyshapelib/">http://ftp.intevation.de/users/bh/pyshapelib</a>.  A new version not using swig is 
+<li> Bernhard Herzog has produced <b>python</b> bindings for Shapelib with
+SWIG, available at <a href="http://ftp.intevation.de/users/bh/pyshapelib/">http://ftp.intevation.de/users/bh/pyshapelib</a>.  A new version not using swig is
 available as <a href="http://wald.intevation.org/plugins/scmsvn/viewcvs.php/trunk/thuban/libraries/pyshapelib/?root=thuban">part of Thuban</a>.<p>
 
 <li> <a href="http://www.triplexware.huckfinn.de/shpapi.html">Delphi</a>
 bindings for Shapelib courtesy of Alexander Weidauer.<p>
 
-<li> Miguel Filgueiras has implemented 
+<li> Miguel Filgueiras has implemented
 <a href="http://www.ncc.up.pt/gpsmanshp/">Tcl</a> bindings for Shapelib
 as part of <a href="http://www.ncc.up.pt/gpsman/">GPSMan</a>.<p>
 
 <li> David Gancarz has implemented a Microsoft
 <a href="dl/contrib/DotNetArchive.zip">.NET wrapper</a> for
-Shapelib.   An example of using shapelib with VB6 is also icluded in the .NET wrapper project file.<p>
+Shapelib.   An example of using shapelib with VB6 is also included in the .NET wrapper project file.<p>
 
-<li> Andrey Hristov (php at hristov dot com) has developed a PHP extension 
+<li> Andrey Hristov (php at hristov dot com) has developed a PHP extension
 based on Shapelib.  It can be found in CVS at http://cvs.php.net/pecl/shp.<p>
 
 <li> Toyoda Eizi has developed Ruby bindings found at
@@ -200,11 +194,11 @@ files.  He maintains a <a href="http://intevation.de/~jan/gen2shp">web page</a>
 
 <li> Tom Russo has implemented a shpcs2cs program, which reprojects shapefiles
 using arguments similar to the PROJ.4 cs2cs program including datum conversion.
-Use as an alternate to the contrib/shpproj which doesn't do datums.  It is 
+Use as an alternate to the contrib/shpproj which doesn't do datums.  It is
 available at the bottom of Tom's <a href="http://www.swcp.com/~russo/shape_web/">Xastir Shapefile Resources</a> page. <p>
 
-<li> 
-Andrew Williamson's 
+<li>
+Andrew Williamson's
 <a href="http://www.geocities.com/SiliconValley/Haven/2295/useful.html">Useful
 Scripts and Stuff</a> page for ArcView, which includes ShapeChecker.<p>
 
@@ -216,13 +210,13 @@ VB access to Shapefiles.  Also available <a href="http://shapelib.maptools.org/d
 
 <li> The <a href="http://arcscripts.esri.com/details.asp?dbid=11810">ShapeFile Read/Write OCX</a> is another option for Visual Basic programmers.<p>
 
-<li> <a href="http://www.casa.ucl.ac.uk/sanjay/software_isovistanalyst.htm">Isovist Analyst</a> is a sort-of-free isovist generating extension for 
+<li> <a href="http://www.casa.ucl.ac.uk/sanjay/software_isovistanalyst.htm">Isovist Analyst</a> is a sort-of-free isovist generating extension for
 ArcView using shapelib.<p>
 
-<li> <a href="http://www.obviously.com/gis/shpdiff/">shpdiff</a> utility 
+<li> <a href="http://www.obviously.com/gis/shpdiff/">shpdiff</a> utility
 by Bryce Nesbitt.<p>
 
-<li> <a href="http://www.aequometer.de/">Aequometer</a>: a program for 
+<li> <a href="http://www.aequometer.de/">Aequometer</a>: a program for
 MS Excel to calculate the area of polygons and export as shapefiles.<p>
 
 </ul>
index d773e3e56867e091437f1613926552a9622d8432..55900bd6fdcd0ced6d4b9c4316fc4bb6f168383b 100644 (file)
@@ -31,7 +31,7 @@ a Shapefile must be of the same type (with the exception of NULL shapes). <p>
 
   3D Shape Types (may include "measure" values for vertices):
 
-  #define SHPT_POINTZ          11      
+  #define SHPT_POINTZ          11
   #define SHPT_ARCZ            13
   #define SHPT_POLYGONZ                15
   #define SHPT_MULTIPOINTZ     18
@@ -66,9 +66,9 @@ should be disposed of with SHPDestroyObject().<p>
     int                nParts;         # of Parts (0 implies single part with no info)
     int                *panPartStart;  Start Vertex of part
     int                *panPartType;   Part Type (SHPP_RING if not SHPT_MULTIPATCH)
-    
-    int                nVertices;      Vertex list 
-    double     *padfX;         
+
+    int                nVertices;      Vertex list
+    double     *padfX;
     double     *padfY;
     double     *padfZ;         (all zero if not provided)
     double     *padfM;         (all zero if not provided)
@@ -97,15 +97,15 @@ SHPHandle SHPOpen( const char * pszShapeFile, const char * pszAccess );
                        just be the path plus the basename of the pair.
 
   pszAccess:           The fopen() style access string.  At this time only
-                       "rb" (read-only binary) and "rb+" (read/write binary) 
+                       "rb" (read-only binary) and "rb+" (read/write binary)
                        should be used.
 </pre>
 
   The SHPOpen() function should be used to establish access to the two files
-  for accessing vertices (.shp and .shx).  Note that both files have to 
+  for accessing vertices (.shp and .shx).  Note that both files have to
   be in the indicated directory, and must have the expected extensions in
-  lower case.  The returned SHPHandle is passed to other access functions, 
-  and SHPClose() should be invoked to recover resources, and flush changes 
+  lower case.  The returned SHPHandle is passed to other access functions,
+  and SHPClose() should be invoked to recover resources, and flush changes
   to disk when complete.<p>
 
 <!-------------------------------------------------------------------------->
@@ -116,7 +116,7 @@ SHPHandle SHPOpen( const char * pszShapeFile, const char * pszAccess );
 void SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
                  double * padfMinBound, double * padfMaxBound );
 
-  hSHP:                        The handle previously returned by SHPOpen() 
+  hSHP:                        The handle previously returned by SHPOpen()
                        or SHPCreate().
 
   pnEntities:          A pointer to an integer into which the number of
@@ -124,20 +124,20 @@ void SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
 
   pnShapetype:         A pointer to an integer into which the shapetype
                        of this file should be placed.  Shapefiles may contain
-                       either SHPT_POINT, SHPT_ARC, SHPT_POLYGON or 
+                       either SHPT_POINT, SHPT_ARC, SHPT_POLYGON or
                        SHPT_MULTIPOINT entities.  This may be NULL.
 
   padfMinBound:                The X, Y, Z and M minimum values will be placed into
                         this four entry array.  This may be NULL.
-                       
+
   padfMaxBound:                The X, Y, Z and M maximum values will be placed into
                         this four entry array.  This may be NULL.
 </pre>
 
  The SHPGetInfo() function retrieves various information about shapefile
- as a whole.  The bounds are read from the file header, and may be 
+ as a whole.  The bounds are read from the file header, and may be
  inaccurate if the file was improperly generated. <p>
-                       
+
 <!-------------------------------------------------------------------------->
 
 <h2>SHPReadObject()</h2>
@@ -145,10 +145,10 @@ void SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
 <pre>
 SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
 
-  hSHP:                        The handle previously returned by SHPOpen() 
+  hSHP:                        The handle previously returned by SHPOpen()
                        or SHPCreate().
 
-  iShape:              The entity number of the shape to read.  Entity 
+  iShape:              The entity number of the shape to read.  Entity
                        numbers are between 0 and nEntities-1 (as returned
                        by SHPGetInfo()).
 </pre>
@@ -156,7 +156,7 @@ SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
   The SHPReadObject() call is used to read a single structure, or entity
   from the shapefile.  See the definition of the SHPObject structure for
   detailed information on fields of a SHPObject.  SHPObject's returned from
-  SHPReadObject() should be deallocated with SHPDestroyShape().  
+  SHPReadObject() should be deallocated with SHPDestroyShape().
   SHPReadObject() will return NULL if an illegal iShape value is requested.<p>
 
   Note that the bounds placed into the SHPObject are those read from the
@@ -175,7 +175,7 @@ SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
 <pre>
 void   SHPClose( SHPHandle hSHP );
 
-  hSHP:                        The handle previously returned by SHPOpen() 
+  hSHP:                        The handle previously returned by SHPOpen()
                        or SHPCreate().
 </pre>
 
@@ -196,7 +196,7 @@ SHPHandle SHPCreate( const char * pszShapeFile, int nShapeType );
                        just be the path plus the basename of the pair.
 
   nShapeType:          The type of shapes to be stored in the newly created
-                       file.  It may be either SHPT_POINT, SHPT_ARC, 
+                       file.  It may be either SHPT_POINT, SHPT_ARC,
                        SHPT_POLYGON or SHPT_MULTIPOINT.
 </pre>
 
@@ -208,15 +208,15 @@ SHPHandle SHPCreate( const char * pszShapeFile, int nShapeType );
 <h2>SHPCreateSimpleObject()</h2>
 
 <pre>
-SHPObject * 
-     SHPCreateSimpleObject( int nSHPType, int nVertices, 
+SHPObject *
+     SHPCreateSimpleObject( int nSHPType, int nVertices,
                            double *padfX, double * padfY, double *padfZ, );
 
   nSHPType:            The SHPT_ type of the object to be created, such
                         as SHPT_POINT, or SHPT_POLYGON.
-  
-  nVertices:           The number of vertices being passed in padfX,    
-                        padfY, and padfZ. 
+
+  nVertices:           The number of vertices being passed in padfX,
+                        padfY, and padfZ.
 
   padfX:               An array of nVertices X coordinates of the vertices
                         for this object.
@@ -229,7 +229,7 @@ SHPObject *
                        they are all assumed to be zero.
 </pre>
 
-  The SHPCreateSimpleObject() allows for the convenient creation of 
+  The SHPCreateSimpleObject() allows for the convenient creation of
   simple objects.  This is normally used so that the SHPObject can be
   passed to SHPWriteObject() to write it to the file.  The simple object
   creation API assumes an M (measure) value of zero for each vertex.  For
@@ -240,7 +240,7 @@ SHPObject *
   SHPDestroyObject() function should be used to free resources associated with
   an object allocated with SHPCreateSimpleObject(). <p>
 
-  This function computes a bounding box for the SHPObject from the given 
+  This function computes a bounding box for the SHPObject from the given
   vertices.<p>
 
 <!-------------------------------------------------------------------------->
@@ -248,10 +248,10 @@ SHPObject *
 <h2>SHPCreateObject()</h2>
 
 <pre>
-SHPObject * 
+SHPObject *
      SHPCreateObject( int nSHPType, int iShape,
                       int nParts, int * panPartStart, int * panPartType,
-                      int nVertices, double *padfX, double * padfY, 
+                      int nVertices, double *padfX, double * padfY,
                       double *padfZ, double *padfM );
 
   nSHPType:            The SHPT_ type of the object to be created, such
@@ -260,19 +260,19 @@ SHPObject *
   iShape:              The shapeid to be recorded with this shape.
 
   nParts:              The number of parts for this object.  If this is
-                        zero for ARC, or POLYGON type objects, a single 
+                        zero for ARC, or POLYGON type objects, a single
                         zero valued part will be created internally.
-  
+
   panPartStart:                The list of zero based start vertices for the rings
                         (parts) in this object.  The first should always be
                         zero.  This may be NULL if nParts is 0.
-  
+
   panPartType:         The type of each of the parts.  This is only meaningful
                         for MULTIPATCH files.  For all other cases this may
                         be NULL, and will be assumed to be SHPP_RING.
-  
-  nVertices:           The number of vertices being passed in padfX,    
-                        padfY, and padfZ. 
+
+  nVertices:           The number of vertices being passed in padfX,
+                        padfY, and padfZ.
 
   padfX:               An array of nVertices X coordinates of the vertices
                         for this object.
@@ -284,19 +284,19 @@ SHPObject *
                         for this object.  This may be NULL in which case
                        they are all assumed to be zero.
 
-  padfM:               An array of nVertices M (measure values) of the 
-                       vertices for this object.  This may be NULL in which 
+  padfM:               An array of nVertices M (measure values) of the
+                       vertices for this object.  This may be NULL in which
                        case they are all assumed to be zero.
 </pre>
 
-  The SHPCreateSimpleObject() allows for the creation of objects (shapes).  
-  This is normally used so that the SHPObject can be passed to 
+  The SHPCreateSimpleObject() allows for the creation of objects (shapes).
+  This is normally used so that the SHPObject can be passed to
   SHPWriteObject() to write it to the file. <p>
 
-  The SHPDestroyObject() function should be used to free resources associated 
+  The SHPDestroyObject() function should be used to free resources associated
   with an object allocated with SHPCreateObject(). <p>
 
-  This function computes a bounding box for the SHPObject from the given 
+  This function computes a bounding box for the SHPObject from the given
   vertices.<p>
 
 <!-------------------------------------------------------------------------->
@@ -308,9 +308,9 @@ void SHPComputeExtents( SHPObject * psObject );
 
   psObject:            An existing shape object to be updated in place.
 </pre>
+
   This function will recompute the extents of this shape, replacing the
-  existing values of the dfXMin, dfYMin, dfZMin, dfMMin, dfXMax, dfYMax, 
+  existing values of the dfXMin, dfYMin, dfZMin, dfMMin, dfXMax, dfYMax,
   dfZMax, and dfMMax values based on the current set of vertices for the
   shape.   This function is automatically called by SHPCreateObject() but
   if the vertices of an existing object are altered it should be called again
@@ -323,14 +323,14 @@ void SHPComputeExtents( SHPObject * psObject );
 <pre>
 int SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject *psObject );
 
-  hSHP:                        The handle previously returned by SHPOpen("r+") 
+  hSHP:                        The handle previously returned by SHPOpen("r+")
                        or SHPCreate().
 
   iShape:              The entity number of the shape to write.  A value of
-                       -1 should be used for new shapes.  
+                       -1 should be used for new shapes.
 
   psObject:            The shape to write to the file. This should have
-                        been created with SHPCreateObject(), or 
+                        been created with SHPCreateObject(), or
                         SHPCreateSimpleObject().
 </pre>
 
@@ -368,7 +368,7 @@ int SHPRewindObject( SHPHandle hSHP, SHPObject *psObject );
   This function will reverse any rings necessary in order to enforce the
   shapefile restrictions on the required order of inner and outer rings in
   the Shapefile specification.  It returns TRUE if a change is made and FALSE
-  if no change is made.  Only polygon objects will be affected though any   
+  if no change is made.  Only polygon objects will be affected though any
   object may be passed.
   <p>
 
index 2fcff96dabae68aeb7b33b65cadf105328645176..2cf982ddf740e4a638e567e36ac6706c92372598 100644 (file)
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: shpopen.c,v 1.78 2019-02-28 15:55:23 erouault Exp $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of core Shapefile read/write functions.
  *
  ******************************************************************************
  * Copyright (c) 1999, 2001, Frank Warmerdam
- * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2011-2019, Even Rouault <even dot rouault at spatialys.com>
  *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING).  This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- *
- * $Log: shpopen.c,v $
- * Revision 1.78  2019-02-28 15:55:23  erouault
- * * shpopen.c: resync with GDAL internal shapelib to avoid being dependent
- * on correctness of file size field in .shp. Fixes
- * https://lists.osgeo.org/pipermail/gdal-dev/2018-October/049218.html
- *
- * Revision 1.77  2018-08-16 15:39:07  erouault
- * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
- * internal shapelib. Mostly to allow building those files as C++
- * without warning. Also add FTDate entry in DBFFieldType
- * (see https://github.com/OSGeo/gdal/pull/308). And some other
- * code cleanups
- *
- * Revision 1.76  2017-09-10 10:11:36  erouault
- * * shpopen.c: resync with GDAL copy. Make sure to zero terminate all
- * error messages. And fix regression regarding re-writing the last shape
- * of a file (https://trac.osgeo.org/gdal/ticket/7031)
- *
- * Revision 1.75  2016-12-05 12:44:05  erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.74  2016-12-04 15:30:15  erouault
- * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
- * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
- * structures extended with new members. New functions:
- * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
- * SHPSetFastModeReadObject
- *
- * * sbnsearch.c: new file to implement original ESRI .sbn spatial
- * index reading. (no write support). New functions:
- * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
- * SBNSearchDiskTreeInteger, SBNSearchFreeIds
- *
- * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
- * with new file and symbols.
- *
- * * commit: helper script to cvs commit
- *
- * Revision 1.73  2012-01-24 22:33:01  fwarmerdam
- * fix memory leak on failure to open .shp (gdal #4410)
- *
- * Revision 1.72  2011-12-11 22:45:28  fwarmerdam
- * fix failure return from SHPOpenLL.
- *
- * Revision 1.71  2011-09-15 03:33:58  fwarmerdam
- * fix missing cast (#2344)
- *
- * Revision 1.70  2011-07-24 05:59:25  fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.69  2011-07-24 03:24:22  fwarmerdam
- * fix memory leaks in error cases creating shapefiles (#2061)
- *
- * Revision 1.68  2010-08-27 23:42:52  fwarmerdam
- * add SHPAPI_CALL attribute in code
- *
- * Revision 1.67  2010-07-01 08:15:48  fwarmerdam
- * do not error out on an object with zero vertices
- *
- * Revision 1.66  2010-07-01 07:58:57  fwarmerdam
- * minor cleanup of error handling
- *
- * Revision 1.65  2010-07-01 07:27:13  fwarmerdam
- * white space formatting adjustments
- *
- * Revision 1.64  2010-01-28 11:34:34  fwarmerdam
- * handle the shape file length limits more gracefully (#3236)
- *
- * Revision 1.63  2010-01-28 04:04:40  fwarmerdam
- * improve numerical accuracy of SHPRewind() algs (gdal #3363)
- *
- * Revision 1.62  2010-01-17 05:34:13  fwarmerdam
- * Remove asserts on x/y being null (#2148).
- *
- * Revision 1.61  2010-01-16 05:07:42  fwarmerdam
- * allow 0/nulls in shpcreateobject (#2148)
- *
- * Revision 1.60  2009-09-17 20:50:02  bram
- * on Win32, define snprintf as alias to _snprintf
- *
- * Revision 1.59  2008-03-14 05:25:31  fwarmerdam
- * Correct crash on buggy geometries (gdal #2218)
- *
- * Revision 1.58  2008/01/08 23:28:26  bram
- * on line 2095, use a float instead of a double to avoid a compiler warning
- *
- * Revision 1.57  2007/12/06 07:00:25  fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.56  2007/12/04 20:37:56  fwarmerdam
- * preliminary implementation of hooks api for io and errors
- *
- * Revision 1.55  2007/11/21 22:39:56  fwarmerdam
- * close shx file in readonly mode (GDAL #1956)
- *
- * Revision 1.54  2007/11/15 00:12:47  mloskot
- * Backported recent changes from GDAL (Ticket #1415) to Shapelib.
- *
- * Revision 1.53  2007/11/14 22:31:08  fwarmerdam
- * checks after mallocs to detect for corrupted/voluntary broken shapefiles.
- * http://trac.osgeo.org/gdal/ticket/1991
- *
- * Revision 1.52  2007/06/21 15:58:33  fwarmerdam
- * fix for SHPRewindObject when rings touch at one vertex (gdal #976)
- *
- * Revision 1.51  2006/09/04 15:24:01  fwarmerdam
- * Fixed up log message for 1.49.
- *
- * Revision 1.50  2006/09/04 15:21:39  fwarmerdam
- * fix of last fix
- *
- * Revision 1.49  2006/09/04 15:21:00  fwarmerdam
- * MLoskot: Added stronger test of Shapefile reading failures, e.g. truncated
- * files.  The problem was discovered by Tim Sutton and reported here
- *   https://svn.qgis.org/trac/ticket/200
- *
- * Revision 1.48  2006/01/26 15:07:32  fwarmerdam
- * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
- *
- * Revision 1.47  2006/01/04 20:07:23  fwarmerdam
- * In SHPWriteObject() make sure that the record length is updated
- * when rewriting an existing record.
- *
- * Revision 1.46  2005/02/11 17:17:46  fwarmerdam
- * added panPartStart[0] validation
- *
- * Revision 1.45  2004/09/26 20:09:48  fwarmerdam
- * const correctness changes
- *
- * Revision 1.44  2003/12/29 00:18:39  fwarmerdam
- * added error checking for failed IO and optional CPL error reporting
- *
- * Revision 1.43  2003/12/01 16:20:08  warmerda
- * be careful of zero vertex shapes
- *
- * Revision 1.42  2003/12/01 14:58:27  warmerda
- * added degenerate object check in SHPRewindObject()
- *
- * Revision 1.41  2003/07/08 15:22:43  warmerda
- * avoid warning
- *
- * Revision 1.40  2003/04/21 18:30:37  warmerda
- * added header write/update public methods
- *
- * Revision 1.39  2002/08/26 06:46:56  warmerda
- * avoid c++ comments
- *
- * Revision 1.38  2002/05/07 16:43:39  warmerda
- * Removed debugging printf()
- *
- * Revision 1.37  2002/04/10 17:35:22  warmerda
- * fixed bug in ring reversal code
- *
- * Revision 1.36  2002/04/10 16:59:54  warmerda
- * added SHPRewindObject
- *
- * Revision 1.35  2001/12/07 15:10:44  warmerda
- * fix if .shx fails to open
- *
- * Revision 1.34  2001/11/01 16:29:55  warmerda
- * move pabyRec into SHPInfo for thread safety
- *
- * Revision 1.33  2001/07/03 12:18:15  warmerda
- * Improved cleanup if SHX not found, provided by Riccardo Cohen.
- *
- * Revision 1.32  2001/06/22 01:58:07  warmerda
- * be more careful about establishing initial bounds in face of NULL shapes
- *
- * Revision 1.31  2001/05/31 19:35:29  warmerda
- * added support for writing null shapes
- *
- * Revision 1.30  2001/05/28 12:46:29  warmerda
- * Add some checking on reasonableness of record count when opening.
- *
- * Revision 1.29  2001/05/23 13:36:52  warmerda
- * added use of SHPAPI_CALL
- *
- * Revision 1.28  2001/02/06 22:25:06  warmerda
- * fixed memory leaks when SHPOpen() fails
- *
- * Revision 1.27  2000/07/18 15:21:33  warmerda
- * added better enforcement of -1 for append in SHPWriteObject
- *
- * Revision 1.26  2000/02/16 16:03:51  warmerda
- * added null shape support
- *
- * Revision 1.25  1999/12/15 13:47:07  warmerda
- * Fixed record size settings in .shp file (was 4 words too long)
- * Added stdlib.h.
- *
- * Revision 1.24  1999/11/05 14:12:04  warmerda
- * updated license terms
- *
- * Revision 1.23  1999/07/27 00:53:46  warmerda
- * added support for rewriting shapes
- *
- * Revision 1.22  1999/06/11 19:19:11  warmerda
- * Cleanup pabyRec static buffer on SHPClose().
- *
- * Revision 1.21  1999/06/02 14:57:56  kshih
- * Remove unused variables
- *
- * Revision 1.20  1999/04/19 21:04:17  warmerda
- * Fixed syntax error.
- *
- * Revision 1.19  1999/04/19 21:01:57  warmerda
- * Force access string to binary in SHPOpen().
- *
- * Revision 1.18  1999/04/01 18:48:07  warmerda
- * Try upper case extensions if lower case doesn't work.
- *
- * Revision 1.17  1998/12/31 15:29:39  warmerda
- * Disable writing measure values to multipatch objects if
- * DISABLE_MULTIPATCH_MEASURE is defined.
- *
- * Revision 1.16  1998/12/16 05:14:33  warmerda
- * Added support to write MULTIPATCH.  Fixed reading Z coordinate of
- * MULTIPATCH. Fixed record size written for all feature types.
- *
- * Revision 1.15  1998/12/03 16:35:29  warmerda
- * r+b is proper binary access string, not rb+.
- *
- * Revision 1.14  1998/12/03 15:47:56  warmerda
- * Fixed setting of nVertices in SHPCreateObject().
- *
- * Revision 1.13  1998/12/03 15:33:54  warmerda
- * Made SHPCalculateExtents() separately callable.
- *
- * Revision 1.12  1998/11/11 20:01:50  warmerda
- * Fixed bug writing ArcM/Z, and PolygonM/Z for big endian machines.
- *
- * Revision 1.11  1998/11/09 20:56:44  warmerda
- * Fixed up handling of file wide bounds.
- *
- * Revision 1.10  1998/11/09 20:18:51  warmerda
- * Converted to support 3D shapefiles, and use of SHPObject.
- *
- * Revision 1.9  1998/02/24 15:09:05  warmerda
- * Fixed memory leak.
- *
- * Revision 1.8  1997/12/04 15:40:29  warmerda
- * Fixed byte swapping of record number, and record length fields in the
- * .shp file.
- *
- * Revision 1.7  1995/10/21 03:15:58  warmerda
- * Added support for binary file access, the magic cookie 9997
- * and tried to improve the int32 selection logic for 16bit systems.
- *
- * Revision 1.6  1995/09/04  04:19:41  warmerda
- * Added fix for file bounds.
- *
- * Revision 1.5  1995/08/25  15:16:44  warmerda
- * Fixed a couple of problems with big endian systems ... one with bounds
- * and the other with multipart polygons.
- *
- * Revision 1.4  1995/08/24  18:10:17  warmerda
- * Switch to use SfRealloc() to avoid problems with pre-ANSI realloc()
- * functions (such as on the Sun).
- *
- * Revision 1.3  1995/08/23  02:23:15  warmerda
- * Added support for reading bounds, and fixed up problems in setting the
- * file wide bounds.
- *
- * Revision 1.2  1995/08/04  03:16:57  warmerda
- * Added header.
- *
- */
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+ ******************************************************************************/
 
 #include "shapefil.h"
 
-#include <math.h>
-#include <limits.h>
 #include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-SHP_CVSID("$Id: shpopen.c,v 1.78 2019-02-28 15:55:23 erouault Exp $")
-
-typedef unsigned char uchar;
-
-#if UINT_MAX == 65535
-typedef unsigned long        int32;
-#else
-typedef unsigned int         int32;
-#endif
 
 #ifndef FALSE
-#  define FALSE                0
-#  define TRUE         1
+#define FALSE 0
+#define TRUE 1
 #endif
 
-#define ByteCopy( a, b, c )    memcpy( b, a, c )
+#define ByteCopy(a, b, c) memcpy(b, a, c)
 #ifndef MAX
-#  define MIN(a,b)      ((a<b) ? a : b)
-#  define MAX(a,b)      ((a>b) ? a : b)
+#define MIN(a, b) ((a < b) ? a : b)
+#define MAX(a, b) ((a > b) ? a : b)
 #endif
 
 #ifndef USE_CPL
 #if defined(_MSC_VER)
-# if _MSC_VER < 1900
-#     define snprintf _snprintf
-# endif
+#if _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
 #elif defined(WIN32) || defined(_WIN32)
-#  ifndef snprintf
-#     define snprintf _snprintf
-#  endif
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
 #endif
 #endif
 
 #ifndef CPL_UNUSED
 #if defined(__GNUC__) && __GNUC__ >= 4
-#  define CPL_UNUSED __attribute((__unused__))
+#define CPL_UNUSED __attribute((__unused__))
 #else
-#  define CPL_UNUSED
+#define CPL_UNUSED
+#endif
 #endif
-#endif  
 
+#ifndef bBigEndian
 #if defined(CPL_LSB)
-#define bBigEndian FALSE
+#define bBigEndian false
 #elif defined(CPL_MSB)
-#define bBigEndian TRUE
+#define bBigEndian true
 #else
-static int     bBigEndian;
+#ifndef static_var_bBigEndian_defined
+#define static_var_bBigEndian_defined
+static bool bBigEndian = false;
+#endif
+#endif
 #endif
 
 #ifdef __cplusplus
-#define STATIC_CAST(type,x) static_cast<type>(x)
+#define STATIC_CAST(type, x) static_cast<type>(x)
 #define SHPLIB_NULLPTR nullptr
 #else
-#define STATIC_CAST(type,x) ((type)(x))
+#define STATIC_CAST(type, x) ((type)(x))
 #define SHPLIB_NULLPTR NULL
 #endif
 
@@ -377,210 +81,200 @@ static int       bBigEndian;
 /*      Swap a 2, 4 or 8 byte word.                                     */
 /************************************************************************/
 
-static void    SwapWord( int length, void * wordP )
-
+#ifndef SwapWord_defined
+#define SwapWord_defined
+static void SwapWord(int length, void *wordP)
 {
-    int                i;
-    uchar      temp;
-
-    for( i=0; i < length/2; i++ )
+    for (int i = 0; i < length / 2; i++)
     {
-       temp = STATIC_CAST(uchar*, wordP)[i];
-       STATIC_CAST(uchar*, wordP)[i] = STATIC_CAST(uchar*, wordP)[length-i-1];
-       STATIC_CAST(uchar*, wordP)[length-i-1] = temp;
+        const unsigned char temp = STATIC_CAST(unsigned char *, wordP)[i];
+        STATIC_CAST(unsigned char *, wordP)
+        [i] = STATIC_CAST(unsigned char *, wordP)[length - i - 1];
+        STATIC_CAST(unsigned char *, wordP)[length - i - 1] = temp;
     }
 }
-
-/************************************************************************/
-/*                             SfRealloc()                              */
-/*                                                                      */
-/*      A realloc cover function that will access a NULL pointer as     */
-/*      a valid input.                                                  */
-/************************************************************************/
-
-static void * SfRealloc( void * pMem, int nNewSize )
-
-{
-    if( pMem == SHPLIB_NULLPTR )
-        return malloc(nNewSize);
-    else
-        return realloc(pMem,nNewSize);
-}
+#endif
 
 /************************************************************************/
 /*                          SHPWriteHeader()                            */
 /*                                                                      */
-/*      Write out a header for the .shp and .shx files as well as the  */
-/*     contents of the index (.shx) file.                              */
+/*      Write out a header for the .shp and .shx files as well as the   */
+/*      contents of the index (.shx) file.                              */
 /************************************************************************/
 
-void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
-
+void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP)
 {
-    uchar      abyHeader[100] = { 0 };
-    int                i;
-    int32      i32;
-    double     dValue;
-    int32      *panSHX;
-
     if (psSHP->fpSHX == SHPLIB_NULLPTR)
     {
-        psSHP->sHooks.Error( "SHPWriteHeader failed : SHX file is closed");
+        psSHP->sHooks.Error("SHPWriteHeader failed : SHX file is closed");
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Prepare header block for .shp file.                             */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      Prepare header block for .shp file.                             */
+    /* -------------------------------------------------------------------- */
 
-    abyHeader[2] = 0x27;                               /* magic cookie */
+    unsigned char abyHeader[100] = {0};
+    abyHeader[2] = 0x27; /* magic cookie */
     abyHeader[3] = 0x0a;
 
-    i32 = psSHP->nFileSize/2;                          /* file size */
-    ByteCopy( &i32, abyHeader+24, 4 );
-    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    uint32_t i32 = psSHP->nFileSize / 2; /* file size */
+    ByteCopy(&i32, abyHeader + 24, 4);
+    if (!bBigEndian)
+        SwapWord(4, abyHeader + 24);
 
-    i32 = 1000;                                                /* version */
-    ByteCopy( &i32, abyHeader+28, 4 );
-    if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+    i32 = 1000; /* version */
+    ByteCopy(&i32, abyHeader + 28, 4);
+    if (bBigEndian)
+        SwapWord(4, abyHeader + 28);
 
-    i32 = psSHP->nShapeType;                           /* shape type */
-    ByteCopy( &i32, abyHeader+32, 4 );
-    if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+    i32 = psSHP->nShapeType; /* shape type */
+    ByteCopy(&i32, abyHeader + 32, 4);
+    if (bBigEndian)
+        SwapWord(4, abyHeader + 32);
 
-    dValue = psSHP->adBoundsMin[0];                    /* set bounds */
-    ByteCopy( &dValue, abyHeader+36, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+36 );
+    double dValue = psSHP->adBoundsMin[0]; /* set bounds */
+    ByteCopy(&dValue, abyHeader + 36, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 36);
 
     dValue = psSHP->adBoundsMin[1];
-    ByteCopy( &dValue, abyHeader+44, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+44 );
+    ByteCopy(&dValue, abyHeader + 44, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 44);
 
     dValue = psSHP->adBoundsMax[0];
-    ByteCopy( &dValue, abyHeader+52, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+52 );
+    ByteCopy(&dValue, abyHeader + 52, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 52);
 
     dValue = psSHP->adBoundsMax[1];
-    ByteCopy( &dValue, abyHeader+60, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+60 );
+    ByteCopy(&dValue, abyHeader + 60, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 60);
 
-    dValue = psSHP->adBoundsMin[2];                    /* z */
-    ByteCopy( &dValue, abyHeader+68, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+68 );
+    dValue = psSHP->adBoundsMin[2]; /* z */
+    ByteCopy(&dValue, abyHeader + 68, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 68);
 
     dValue = psSHP->adBoundsMax[2];
-    ByteCopy( &dValue, abyHeader+76, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+76 );
+    ByteCopy(&dValue, abyHeader + 76, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 76);
 
-    dValue = psSHP->adBoundsMin[3];                    /* m */
-    ByteCopy( &dValue, abyHeader+84, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+84 );
+    dValue = psSHP->adBoundsMin[3]; /* m */
+    ByteCopy(&dValue, abyHeader + 84, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 84);
 
     dValue = psSHP->adBoundsMax[3];
-    ByteCopy( &dValue, abyHeader+92, 8 );
-    if( bBigEndian ) SwapWord( 8, abyHeader+92 );
+    ByteCopy(&dValue, abyHeader + 92, 8);
+    if (bBigEndian)
+        SwapWord(8, abyHeader + 92);
 
-/* -------------------------------------------------------------------- */
-/*      Write .shp file header.                                         */
-/* -------------------------------------------------------------------- */
-    if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0
-        || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
+    /* -------------------------------------------------------------------- */
+    /*      Write .shp file header.                                         */
+    /* -------------------------------------------------------------------- */
+    if (psSHP->sHooks.FSeek(psSHP->fpSHP, 0, 0) != 0 ||
+        psSHP->sHooks.FWrite(abyHeader, 100, 1, psSHP->fpSHP) != 1)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Failure writing .shp header: %s", strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Failure writing .shp header: %s", strerror(errno));
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Prepare, and write .shx file header.                            */
-/* -------------------------------------------------------------------- */
-    i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2;   /* file size */
-    ByteCopy( &i32, abyHeader+24, 4 );
-    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    /* -------------------------------------------------------------------- */
+    /*      Prepare, and write .shx file header.                            */
+    /* -------------------------------------------------------------------- */
+    i32 = (psSHP->nRecords * 2 * sizeof(uint32_t) + 100) / 2; /* file size */
+    ByteCopy(&i32, abyHeader + 24, 4);
+    if (!bBigEndian)
+        SwapWord(4, abyHeader + 24);
 
-    if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0
-        || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
+    if (psSHP->sHooks.FSeek(psSHP->fpSHX, 0, 0) != 0 ||
+        psSHP->sHooks.FWrite(abyHeader, 100, 1, psSHP->fpSHX) != 1)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Failure writing .shx header: %s", strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Failure writing .shx header: %s", strerror(errno));
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
 
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out the .shx contents.                                    */
-/* -------------------------------------------------------------------- */
-    panSHX = STATIC_CAST(int32 *, malloc(sizeof(int32) * 2 * psSHP->nRecords));
-    if( panSHX == SHPLIB_NULLPTR )
+    /* -------------------------------------------------------------------- */
+    /*      Write out the .shx contents.                                    */
+    /* -------------------------------------------------------------------- */
+    uint32_t *panSHX =
+        STATIC_CAST(uint32_t *, malloc(sizeof(uint32_t) * 2 * psSHP->nRecords));
+    if (panSHX == SHPLIB_NULLPTR)
     {
-        psSHP->sHooks.Error( "Failure allocatin panSHX" );
+        psSHP->sHooks.Error("Failure allocatin panSHX");
         return;
     }
 
-    for( i = 0; i < psSHP->nRecords; i++ )
+    for (int i = 0; i < psSHP->nRecords; i++)
     {
-        panSHX[i*2  ] = psSHP->panRecOffset[i]/2;
-        panSHX[i*2+1] = psSHP->panRecSize[i]/2;
-        if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
-        if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
+        panSHX[i * 2] = psSHP->panRecOffset[i] / 2;
+        panSHX[i * 2 + 1] = psSHP->panRecSize[i] / 2;
+        if (!bBigEndian)
+            SwapWord(4, panSHX + i * 2);
+        if (!bBigEndian)
+            SwapWord(4, panSHX + i * 2 + 1);
     }
 
-    if( STATIC_CAST(int, psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX ))
-        != psSHP->nRecords )
+    if (STATIC_CAST(int, psSHP->sHooks.FWrite(panSHX, sizeof(uint32_t) * 2,
+                                              psSHP->nRecords, psSHP->fpSHX)) !=
+        psSHP->nRecords)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Failure writing .shx contents: %s", strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Failure writing .shx contents: %s", strerror(errno));
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
     }
 
-    free( panSHX );
+    free(panSHX);
 
-/* -------------------------------------------------------------------- */
-/*      Flush to disk.                                                  */
-/* -------------------------------------------------------------------- */
-    psSHP->sHooks.FFlush( psSHP->fpSHP );
-    psSHP->sHooks.FFlush( psSHP->fpSHX );
+    /* -------------------------------------------------------------------- */
+    /*      Flush to disk.                                                  */
+    /* -------------------------------------------------------------------- */
+    psSHP->sHooks.FFlush(psSHP->fpSHP);
+    psSHP->sHooks.FFlush(psSHP->fpSHX);
 }
 
 /************************************************************************/
 /*                              SHPOpen()                               */
 /************************************************************************/
 
-SHPHandle SHPAPI_CALL
-SHPOpen( const char * pszLayer, const char * pszAccess )
-
+SHPHandle SHPAPI_CALL SHPOpen(const char *pszLayer, const char *pszAccess)
 {
     SAHooks sHooks;
 
-    SASetupDefaultHooks( &sHooks );
+    SASetupDefaultHooks(&sHooks);
 
-    return SHPOpenLL( pszLayer, pszAccess, &sHooks );
+    return SHPOpenLL(pszLayer, pszAccess, &sHooks);
 }
 
 /************************************************************************/
 /*                      SHPGetLenWithoutExtension()                     */
 /************************************************************************/
 
-static int SHPGetLenWithoutExtension(const charpszBasename)
+static int SHPGetLenWithoutExtension(const char *pszBasename)
 {
-    int i;
-    int nLen = STATIC_CAST(int, strlen(pszBasename));
-    for( i = nLen-1;
-         i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\';
-         i-- )
+    const int nLen = STATIC_CAST(int, strlen(pszBasename));
+    for (int i = nLen - 1;
+         i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\'; i--)
     {
-        if( pszBasename[i] == '.' )
+        if (pszBasename[i] == '.')
         {
             return i;
         }
@@ -595,27 +289,20 @@ static int SHPGetLenWithoutExtension(const char* pszBasename)
 /*      files or either file name.                                      */
 /************************************************************************/
 
-SHPHandle SHPAPI_CALL
-SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
-
+SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
+                                const SAHooks *psHooks)
 {
-    char        *pszFullname;
-    SHPHandle       psSHP;
-
-    uchar       *pabyBuf;
-    int         i;
-    double      dValue;
-    int         bLazySHXLoading = FALSE;
-    int         nLenWithoutExtension;
-
-/* -------------------------------------------------------------------- */
-/*      Ensure the access string is one of the legal ones.  We          */
-/*      ensure the result string indicates binary to avoid common       */
-/*      problems on Windows.                                            */
-/* -------------------------------------------------------------------- */
-    if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
-        || strcmp(pszAccess,"r+") == 0 )
+    /* -------------------------------------------------------------------- */
+    /*      Ensure the access string is one of the legal ones.  We          */
+    /*      ensure the result string indicates binary to avoid common       */
+    /*      problems on Windows.                                            */
+    /* -------------------------------------------------------------------- */
+    bool bLazySHXLoading = false;
+    if (strcmp(pszAccess, "rb+") == 0 || strcmp(pszAccess, "r+b") == 0 ||
+        strcmp(pszAccess, "r+") == 0)
+    {
         pszAccess = "r+b";
+    }
     else
     {
         bLazySHXLoading = strchr(pszAccess, 'l') != SHPLIB_NULLPTR;
@@ -626,138 +313,145 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /*  Establish the byte order on this machine.           */
 /* -------------------------------------------------------------------- */
 #if !defined(bBigEndian)
-    i = 1;
-    if( *((uchar *) &i) == 1 )
-        bBigEndian = FALSE;
-    else
-        bBigEndian = TRUE;
+    {
+        int i = 1;
+        if (*((unsigned char *)&i) == 1)
+            bBigEndian = false;
+        else
+            bBigEndian = true;
+    }
 #endif
 
-/* -------------------------------------------------------------------- */
-/*  Initialize the info structure.                  */
-/* -------------------------------------------------------------------- */
-    psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo),1));
+    /* -------------------------------------------------------------------- */
+    /*  Initialize the info structure.                  */
+    /* -------------------------------------------------------------------- */
+    SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1));
 
     psSHP->bUpdated = FALSE;
-    memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
-
-/* -------------------------------------------------------------------- */
-/*  Open the .shp and .shx files.  Note that files pulled from  */
-/*  a PC to Unix with upper case filenames won't work!      */
-/* -------------------------------------------------------------------- */
-    nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
-    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
+
+    /* -------------------------------------------------------------------- */
+    /*  Open the .shp and .shx files.  Note that files pulled from  */
+    /*  a PC to Unix with upper case filenames won't work!      */
+    /* -------------------------------------------------------------------- */
+    const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+    char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
     memcpy(pszFullname, pszLayer, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
-    psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
-    if( psSHP->fpSHP == SHPLIB_NULLPTR )
+    psSHP->fpSHP =
+        psSHP->sHooks.FOpen(pszFullname, pszAccess, psSHP->sHooks.pvUserData);
+    if (psSHP->fpSHP == SHPLIB_NULLPTR)
     {
         memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
-        psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
+        psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess,
+                                           psSHP->sHooks.pvUserData);
     }
 
-    if( psSHP->fpSHP == SHPLIB_NULLPTR )
+    if (psSHP->fpSHP == SHPLIB_NULLPTR)
     {
-        size_t nMessageLen = strlen(pszFullname)*2+256;
+        const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
         char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
         pszFullname[nLenWithoutExtension] = 0;
-        snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
-                  pszFullname, pszFullname );
-        psHooks->Error( pszMessage );
-        free( pszMessage );
+        snprintf(pszMessage, nMessageLen,
+                 "Unable to open %s.shp or %s.SHP in %s mode.", pszFullname,
+                 pszFullname, pszAccess);
+        psHooks->Error(pszMessage);
+        free(pszMessage);
 
-        free( psSHP );
-        free( pszFullname );
+        free(psSHP);
+        free(pszFullname);
 
         return SHPLIB_NULLPTR;
     }
 
     memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
-    psSHP->fpSHX =  psSHP->sHooks.FOpen(pszFullname, pszAccess );
-    if( psSHP->fpSHX == SHPLIB_NULLPTR )
+    psSHP->fpSHX =
+        psSHP->sHooks.FOpen(pszFullname, pszAccess, psSHP->sHooks.pvUserData);
+    if (psSHP->fpSHX == SHPLIB_NULLPTR)
     {
         memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
-        psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
+        psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess,
+                                           psSHP->sHooks.pvUserData);
     }
 
-    if( psSHP->fpSHX == SHPLIB_NULLPTR )
+    if (psSHP->fpSHX == SHPLIB_NULLPTR)
     {
-        size_t nMessageLen = strlen(pszFullname)*2+256;
+        const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
         char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
         pszFullname[nLenWithoutExtension] = 0;
-        snprintf( pszMessage, nMessageLen, "Unable to open %s.shx or %s.SHX. "
-                  "Set SHAPE_RESTORE_SHX config option to YES to restore or "
-                  "create it.", pszFullname, pszFullname );
-        psHooks->Error( pszMessage );
-        free( pszMessage );
-
-        psSHP->sHooks.FClose( psSHP->fpSHP );
-        free( psSHP );
-        free( pszFullname );
-        return SHPLIB_NULLPTR ;
+        snprintf(pszMessage, nMessageLen,
+                 "Unable to open %s.shx or %s.SHX. "
+                 "Set SHAPE_RESTORE_SHX config option to YES to restore or "
+                 "create it.",
+                 pszFullname, pszFullname);
+        psHooks->Error(pszMessage);
+        free(pszMessage);
+
+        psSHP->sHooks.FClose(psSHP->fpSHP);
+        free(psSHP);
+        free(pszFullname);
+        return SHPLIB_NULLPTR;
     }
 
-    free( pszFullname );
+    free(pszFullname);
 
-/* -------------------------------------------------------------------- */
-/*  Read the file size from the SHP file.               */
-/* -------------------------------------------------------------------- */
-    pabyBuf = STATIC_CAST(uchar *, malloc(100));
-    if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP ) != 1 )
+    /* -------------------------------------------------------------------- */
+    /*  Read the file size from the SHP file.               */
+    /* -------------------------------------------------------------------- */
+    unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100));
+    if (psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHP) != 1)
     {
-        psSHP->sHooks.Error( ".shp file is unreadable, or corrupt." );
-        psSHP->sHooks.FClose( psSHP->fpSHP );
-        psSHP->sHooks.FClose( psSHP->fpSHX );
-        free( pabyBuf );
-        free( psSHP );
+        psSHP->sHooks.Error(".shp file is unreadable, or corrupt.");
+        psSHP->sHooks.FClose(psSHP->fpSHP);
+        psSHP->sHooks.FClose(psSHP->fpSHX);
+        free(pabyBuf);
+        free(psSHP);
 
-        return SHPLIB_NULLPTR ;
+        return SHPLIB_NULLPTR;
     }
 
-    psSHP->nFileSize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
-                        (pabyBuf[26]<<8)|pabyBuf[27];
-    if( psSHP->nFileSize < UINT_MAX / 2 )
+    psSHP->nFileSize = (STATIC_CAST(unsigned int, pabyBuf[24]) << 24) |
+                       (pabyBuf[25] << 16) | (pabyBuf[26] << 8) | pabyBuf[27];
+    if (psSHP->nFileSize < UINT_MAX / 2)
         psSHP->nFileSize *= 2;
     else
         psSHP->nFileSize = (UINT_MAX / 2) * 2;
 
-/* -------------------------------------------------------------------- */
-/*  Read SHX file Header info                                           */
-/* -------------------------------------------------------------------- */
-    if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
-        || pabyBuf[0] != 0
-        || pabyBuf[1] != 0
-        || pabyBuf[2] != 0x27
-        || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
-    {
-        psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
-        psSHP->sHooks.FClose( psSHP->fpSHP );
-        psSHP->sHooks.FClose( psSHP->fpSHX );
-        free( pabyBuf );
-        free( psSHP );
+    /* -------------------------------------------------------------------- */
+    /*  Read SHX file Header info                                           */
+    /* -------------------------------------------------------------------- */
+    if (psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHX) != 1 ||
+        pabyBuf[0] != 0 || pabyBuf[1] != 0 || pabyBuf[2] != 0x27 ||
+        (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d))
+    {
+        psSHP->sHooks.Error(".shx file is unreadable, or corrupt.");
+        psSHP->sHooks.FClose(psSHP->fpSHP);
+        psSHP->sHooks.FClose(psSHP->fpSHX);
+        free(pabyBuf);
+        free(psSHP);
 
         return SHPLIB_NULLPTR;
     }
 
-    psSHP->nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
-                      ((pabyBuf[24] & 0x7F)<<24);
+    psSHP->nRecords = pabyBuf[27] | (pabyBuf[26] << 8) | (pabyBuf[25] << 16) |
+                      ((pabyBuf[24] & 0x7F) << 24);
     psSHP->nRecords = (psSHP->nRecords - 50) / 4;
 
     psSHP->nShapeType = pabyBuf[32];
 
-    if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
+    if (psSHP->nRecords < 0 || psSHP->nRecords > 256000000)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Record count in .shp header is %d, which seems\n"
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Record count in .shx header is %d, which seems\n"
                  "unreasonable.  Assuming header is corrupt.",
-                 psSHP->nRecords );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
-        psSHP->sHooks.FClose( psSHP->fpSHP );
-        psSHP->sHooks.FClose( psSHP->fpSHX );
-        free( psSHP );
+                 psSHP->nRecords);
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
+        psSHP->sHooks.FClose(psSHP->fpSHP);
+        psSHP->sHooks.FClose(psSHP->fpSHX);
+        free(psSHP);
         free(pabyBuf);
 
         return SHPLIB_NULLPTR;
@@ -765,70 +459,82 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 
     /* If a lot of records are advertized, check that the file is big enough */
     /* to hold them */
-    if( psSHP->nRecords >= 1024 * 1024 )
+    if (psSHP->nRecords >= 1024 * 1024)
     {
-        SAOffset nFileSize;
-        psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 2 );
-        nFileSize = psSHP->sHooks.FTell( psSHP->fpSHX );
-        if( nFileSize > 100 &&
-            nFileSize/2 < STATIC_CAST(SAOffset, psSHP->nRecords * 4 + 50) )
+        psSHP->sHooks.FSeek(psSHP->fpSHX, 0, 2);
+        const SAOffset nFileSize = psSHP->sHooks.FTell(psSHP->fpSHX);
+        if (nFileSize > 100 &&
+            nFileSize / 2 < STATIC_CAST(SAOffset, psSHP->nRecords * 4 + 50))
         {
             psSHP->nRecords = STATIC_CAST(int, (nFileSize - 100) / 8);
         }
-        psSHP->sHooks.FSeek( psSHP->fpSHX, 100, 0 );
+        psSHP->sHooks.FSeek(psSHP->fpSHX, 100, 0);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the bounds.                                                */
-/* -------------------------------------------------------------------- */
-    if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
-    memcpy( &dValue, pabyBuf+36, 8 );
+    /* -------------------------------------------------------------------- */
+    /*      Read the bounds.                                                */
+    /* -------------------------------------------------------------------- */
+    double dValue;
+
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 36);
+    memcpy(&dValue, pabyBuf + 36, 8);
     psSHP->adBoundsMin[0] = dValue;
 
-    if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
-    memcpy( &dValue, pabyBuf+44, 8 );
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 44);
+    memcpy(&dValue, pabyBuf + 44, 8);
     psSHP->adBoundsMin[1] = dValue;
 
-    if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
-    memcpy( &dValue, pabyBuf+52, 8 );
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 52);
+    memcpy(&dValue, pabyBuf + 52, 8);
     psSHP->adBoundsMax[0] = dValue;
 
-    if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
-    memcpy( &dValue, pabyBuf+60, 8 );
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 60);
+    memcpy(&dValue, pabyBuf + 60, 8);
     psSHP->adBoundsMax[1] = dValue;
 
-    if( bBigEndian ) SwapWord( 8, pabyBuf+68 );     /* z */
-    memcpy( &dValue, pabyBuf+68, 8 );
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 68); /* z */
+    memcpy(&dValue, pabyBuf + 68, 8);
     psSHP->adBoundsMin[2] = dValue;
 
-    if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
-    memcpy( &dValue, pabyBuf+76, 8 );
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 76);
+    memcpy(&dValue, pabyBuf + 76, 8);
     psSHP->adBoundsMax[2] = dValue;
 
-    if( bBigEndian ) SwapWord( 8, pabyBuf+84 );     /* z */
-    memcpy( &dValue, pabyBuf+84, 8 );
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 84); /* z */
+    memcpy(&dValue, pabyBuf + 84, 8);
     psSHP->adBoundsMin[3] = dValue;
 
-    if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
-    memcpy( &dValue, pabyBuf+92, 8 );
+    if (bBigEndian)
+        SwapWord(8, pabyBuf + 92);
+    memcpy(&dValue, pabyBuf + 92, 8);
     psSHP->adBoundsMax[3] = dValue;
 
-    free( pabyBuf );
+    free(pabyBuf);
 
-/* -------------------------------------------------------------------- */
-/*  Read the .shx file to get the offsets to each record in     */
-/*  the .shp file.                          */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*  Read the .shx file to get the offsets to each record in     */
+    /*  the .shp file.                          */
+    /* -------------------------------------------------------------------- */
     psSHP->nMaxRecords = psSHP->nRecords;
 
-    psSHP->panRecOffset = STATIC_CAST(unsigned int *,
-        malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
-    psSHP->panRecSize = STATIC_CAST(unsigned int *,
-        malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
-    if( bLazySHXLoading )
+    psSHP->panRecOffset =
+        STATIC_CAST(unsigned int *,
+                    malloc(sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords)));
+    psSHP->panRecSize =
+        STATIC_CAST(unsigned int *,
+                    malloc(sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords)));
+    if (bLazySHXLoading)
         pabyBuf = SHPLIB_NULLPTR;
     else
-        pabyBuf = STATIC_CAST(uchar *, malloc(8 * MAX(1,psSHP->nRecords) ));
+        pabyBuf =
+            STATIC_CAST(unsigned char *, malloc(8 * MAX(1, psSHP->nRecords)));
 
     if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
         psSHP->panRecSize == SHPLIB_NULLPTR ||
@@ -836,47 +542,53 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                "Not enough memory to allocate requested memory (nRecords=%d).\n"
-                "Probably broken SHP file",
-                psSHP->nRecords );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
-        psSHP->sHooks.FClose( psSHP->fpSHP );
-        psSHP->sHooks.FClose( psSHP->fpSHX );
-        if (psSHP->panRecOffset) free( psSHP->panRecOffset );
-        if (psSHP->panRecSize) free( psSHP->panRecSize );
-        if (pabyBuf) free( pabyBuf );
-        free( psSHP );
+        snprintf(
+            szErrorMsg, sizeof(szErrorMsg),
+            "Not enough memory to allocate requested memory (nRecords=%d).\n"
+            "Probably broken SHP file",
+            psSHP->nRecords);
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
+        psSHP->sHooks.FClose(psSHP->fpSHP);
+        psSHP->sHooks.FClose(psSHP->fpSHX);
+        if (psSHP->panRecOffset)
+            free(psSHP->panRecOffset);
+        if (psSHP->panRecSize)
+            free(psSHP->panRecSize);
+        if (pabyBuf)
+            free(pabyBuf);
+        free(psSHP);
         return SHPLIB_NULLPTR;
     }
 
-    if( bLazySHXLoading )
+    if (bLazySHXLoading)
     {
-        memset(psSHP->panRecOffset, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
-        memset(psSHP->panRecSize, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
-        free( pabyBuf ); // sometimes make cppcheck happy, but
-        return( psSHP );
+        memset(psSHP->panRecOffset, 0,
+               sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords));
+        memset(psSHP->panRecSize, 0,
+               sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords));
+        free(pabyBuf);  // sometimes make cppcheck happy, but
+        return (psSHP);
     }
 
-    if( STATIC_CAST(int, psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ))
-        != psSHP->nRecords )
+    if (STATIC_CAST(int, psSHP->sHooks.FRead(pabyBuf, 8, psSHP->nRecords,
+                                             psSHP->fpSHX)) != psSHP->nRecords)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
                  "Failed to read all values for %d records in .shx file: %s.",
-                 psSHP->nRecords, strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
+                 psSHP->nRecords, strerror(errno));
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
 
         /* SHX is short or unreadable for some reason. */
-        psSHP->sHooks.FClose( psSHP->fpSHP );
-        psSHP->sHooks.FClose( psSHP->fpSHX );
-        free( psSHP->panRecOffset );
-        free( psSHP->panRecSize );
-        free( pabyBuf );
-        free( psSHP );
+        psSHP->sHooks.FClose(psSHP->fpSHP);
+        psSHP->sHooks.FClose(psSHP->fpSHX);
+        free(psSHP->panRecOffset);
+        free(psSHP->panRecSize);
+        free(pabyBuf);
+        free(psSHP);
 
         return SHPLIB_NULLPTR;
     }
@@ -884,50 +596,50 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     /* In read-only mode, we can close the SHX now */
     if (strcmp(pszAccess, "rb") == 0)
     {
-        psSHP->sHooks.FClose( psSHP->fpSHX );
+        psSHP->sHooks.FClose(psSHP->fpSHX);
         psSHP->fpSHX = SHPLIB_NULLPTR;
     }
 
-    for( i = 0; i < psSHP->nRecords; i++ )
+    for (int i = 0; i < psSHP->nRecords; i++)
     {
-        unsigned int        nOffset, nLength;
-
-        memcpy( &nOffset, pabyBuf + i * 8, 4 );
-        if( !bBigEndian ) SwapWord( 4, &nOffset );
+        unsigned int nOffset;
+        memcpy(&nOffset, pabyBuf + i * 8, 4);
+        if (!bBigEndian)
+            SwapWord(4, &nOffset);
 
-        memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
-        if( !bBigEndian ) SwapWord( 4, &nLength );
+        unsigned int nLength;
+        memcpy(&nLength, pabyBuf + i * 8 + 4, 4);
+        if (!bBigEndian)
+            SwapWord(4, &nLength);
 
-        if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
+        if (nOffset > STATIC_CAST(unsigned int, INT_MAX))
         {
             char str[128];
-            snprintf( str, sizeof(str),
-                    "Invalid offset for entity %d", i);
-            str[sizeof(str)-1] = '\0';
+            snprintf(str, sizeof(str), "Invalid offset for entity %d", i);
+            str[sizeof(str) - 1] = '\0';
 
-            psSHP->sHooks.Error( str );
+            psSHP->sHooks.Error(str);
             SHPClose(psSHP);
-            free( pabyBuf );
+            free(pabyBuf);
             return SHPLIB_NULLPTR;
         }
-        if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
+        if (nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4))
         {
             char str[128];
-            snprintf( str, sizeof(str),
-                    "Invalid length for entity %d", i);
-            str[sizeof(str)-1] = '\0';
+            snprintf(str, sizeof(str), "Invalid length for entity %d", i);
+            str[sizeof(str) - 1] = '\0';
 
-            psSHP->sHooks.Error( str );
+            psSHP->sHooks.Error(str);
             SHPClose(psSHP);
-            free( pabyBuf );
+            free(pabyBuf);
             return SHPLIB_NULLPTR;
         }
-        psSHP->panRecOffset[i] = nOffset*2;
-        psSHP->panRecSize[i] = nLength*2;
+        psSHP->panRecOffset[i] = nOffset * 2;
+        psSHP->panRecSize[i] = nLength * 2;
     }
-    free( pabyBuf );
+    free(pabyBuf);
 
-    return( psSHP );
+    return (psSHP);
 }
 
 /************************************************************************/
@@ -938,17 +650,16 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /*      in case when bRestoreSHX equals true.                           */
 /************************************************************************/
 
-SHPHandle SHPAPI_CALL
-SHPOpenLLEx( const char * pszLayer, const char * pszAccess, SAHooks *psHooks,
-            int bRestoreSHX )
-
+SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszLayer, const char *pszAccess,
+                                  const SAHooks *psHooks, int bRestoreSHX)
 {
-    if ( !bRestoreSHX ) return SHPOpenLL ( pszLayer, pszAccess, psHooks );
+    if (!bRestoreSHX)
+        return SHPOpenLL(pszLayer, pszAccess, psHooks);
     else
     {
-        if ( SHPRestoreSHX ( pszLayer, pszAccess, psHooks ) )
+        if (SHPRestoreSHX(pszLayer, pszAccess, psHooks))
         {
-            return SHPOpenLL ( pszLayer, pszAccess, psHooks );
+            return SHPOpenLL(pszLayer, pszAccess, psHooks);
         }
     }
 
@@ -962,37 +673,19 @@ SHPOpenLLEx( const char * pszLayer, const char * pszAccess, SAHooks *psHooks,
 /*                                                                      */
 /************************************************************************/
 
-int       SHPAPI_CALL
-SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
-
+int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
+                              const SAHooks *psHooks)
 {
-    char            *pszFullname;
-    SAFile          fpSHP, fpSHX;
-
-
-    uchar           *pabyBuf;
-    int             nLenWithoutExtension;
-    unsigned int    nSHPFilesize;
-
-    unsigned int    nCurrentRecordOffset = 0;
-    unsigned int    nCurrentSHPOffset = 100;
-    size_t          nRealSHXContentSize = 100;
-
-    const char      pszSHXAccess[] = "w+b";
-    char            *pabySHXHeader;
-    char            abyReadedRecord[8];
-    unsigned int    niRecord = 0;
-    unsigned int    nRecordLength = 0;
-    unsigned int    nRecordOffset = 50;
-
-/* -------------------------------------------------------------------- */
-/*      Ensure the access string is one of the legal ones.  We          */
-/*      ensure the result string indicates binary to avoid common       */
-/*      problems on Windows.                                            */
-/* -------------------------------------------------------------------- */
-    if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
-        || strcmp(pszAccess,"r+") == 0 )
+    /* -------------------------------------------------------------------- */
+    /*      Ensure the access string is one of the legal ones.  We          */
+    /*      ensure the result string indicates binary to avoid common       */
+    /*      problems on Windows.                                            */
+    /* -------------------------------------------------------------------- */
+    if (strcmp(pszAccess, "rb+") == 0 || strcmp(pszAccess, "r+b") == 0 ||
+        strcmp(pszAccess, "r+") == 0)
+    {
         pszAccess = "r+b";
+    }
     else
     {
         pszAccess = "rb";
@@ -1004,185 +697,253 @@ SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks
 #if !defined(bBigEndian)
     {
         int i = 1;
-        if( *((uchar *) &i) == 1 )
-            bBigEndian = FALSE;
+        if (*((unsigned char *)&i) == 1)
+            bBigEndian = false;
         else
-            bBigEndian = TRUE;
+            bBigEndian = true;
     }
 #endif
 
-/* -------------------------------------------------------------------- */
-/*  Open the .shp file.  Note that files pulled from                    */
-/*  a PC to Unix with upper case filenames won't work!                  */
-/* -------------------------------------------------------------------- */
-    nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
-    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    /* -------------------------------------------------------------------- */
+    /*  Open the .shp file.  Note that files pulled from                    */
+    /*  a PC to Unix with upper case filenames won't work!                  */
+    /* -------------------------------------------------------------------- */
+    const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+    char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
     memcpy(pszFullname, pszLayer, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
-    fpSHP = psHooks->FOpen(pszFullname, pszAccess );
-    if( fpSHP == SHPLIB_NULLPTR )
+    SAFile fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
+    if (fpSHP == SHPLIB_NULLPTR)
     {
         memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
-        fpSHP = psHooks->FOpen(pszFullname, pszAccess );
+        fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
     }
 
-    if( fpSHP == SHPLIB_NULLPTR )
+    if (fpSHP == SHPLIB_NULLPTR)
     {
-        size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
-        char* pszMessage = STATIC_CAST(char *, malloc( nMessageLen ));
+        const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
+        char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
 
         pszFullname[nLenWithoutExtension] = 0;
-        snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
-                  pszFullname, pszFullname );
-        psHooks->Error( pszMessage );
-        free( pszMessage );
+        snprintf(pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
+                 pszFullname, pszFullname);
+        psHooks->Error(pszMessage);
+        free(pszMessage);
 
-        free( pszFullname );
+        free(pszFullname);
 
-        return( 0 );
+        return (0);
     }
 
-/* -------------------------------------------------------------------- */
-/*  Read the file size from the SHP file.                               */
-/* -------------------------------------------------------------------- */
-    pabyBuf = STATIC_CAST(uchar *, malloc(100));
-    psHooks->FRead( pabyBuf, 100, 1, fpSHP );
+    /* -------------------------------------------------------------------- */
+    /*  Read the file size from the SHP file.                               */
+    /* -------------------------------------------------------------------- */
+    unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100));
+    if (psHooks->FRead(pabyBuf, 100, 1, fpSHP) != 1)
+    {
+        psHooks->Error(".shp file is unreadable, or corrupt.");
+        psHooks->FClose(fpSHP);
 
-    nSHPFilesize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
-                   (pabyBuf[26]<<8)|pabyBuf[27];
-    if( nSHPFilesize < UINT_MAX / 2 )
+        free(pabyBuf);
+        free(pszFullname);
+
+        return (0);
+    }
+
+    unsigned int nSHPFilesize = (STATIC_CAST(unsigned int, pabyBuf[24]) << 24) |
+                                (pabyBuf[25] << 16) | (pabyBuf[26] << 8) |
+                                pabyBuf[27];
+    if (nSHPFilesize < UINT_MAX / 2)
         nSHPFilesize *= 2;
     else
         nSHPFilesize = (UINT_MAX / 2) * 2;
 
     memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
-    fpSHX = psHooks->FOpen( pszFullname, pszSHXAccess );
-    if( fpSHX == SHPLIB_NULLPTR )
-    {
-        memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
-        fpSHP = psHooks->FOpen(pszFullname, pszAccess );
-    }
-
-    if( fpSHX == SHPLIB_NULLPTR )
+    const char pszSHXAccess[] = "w+b";
+    SAFile fpSHX =
+        psHooks->FOpen(pszFullname, pszSHXAccess, psHooks->pvUserData);
+    if (fpSHX == SHPLIB_NULLPTR)
     {
-        size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
-        char* pszMessage = STATIC_CAST(char *, malloc( nMessageLen ));
+        size_t nMessageLen = strlen(pszFullname) * 2 + 256;
+        char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
         pszFullname[nLenWithoutExtension] = 0;
-        snprintf( pszMessage, nMessageLen,
-                  "Error opening file %s.shx or %s.SHX for writing",
-                  pszFullname, pszFullname );
-        psHooks->Error( pszMessage );
-        free( pszMessage );
+        snprintf(pszMessage, nMessageLen,
+                 "Error opening file %s.shx for writing", pszFullname);
+        psHooks->Error(pszMessage);
+        free(pszMessage);
 
-        psHooks->FClose( fpSHX );
+        psHooks->FClose(fpSHP);
 
-        free( pabyBuf );
-        free( pszFullname );
+        free(pabyBuf);
+        free(pszFullname);
 
-        return( 0 );
+        return (0);
     }
 
-/* -------------------------------------------------------------------- */
-/*  Open SHX and create it using SHP file content.                      */
-/* -------------------------------------------------------------------- */
-    psHooks->FSeek( fpSHP, 100, 0 );
-    pabySHXHeader = STATIC_CAST(char *, malloc ( 100 ));
-    memcpy( pabySHXHeader, pabyBuf, 100 );
-    psHooks->FWrite( pabySHXHeader, 100, 1, fpSHX );
+    /* -------------------------------------------------------------------- */
+    /*  Open SHX and create it using SHP file content.                      */
+    /* -------------------------------------------------------------------- */
+    psHooks->FSeek(fpSHP, 100, 0);
+    char *pabySHXHeader = STATIC_CAST(char *, malloc(100));
+    memcpy(pabySHXHeader, pabyBuf, 100);
+    psHooks->FWrite(pabySHXHeader, 100, 1, fpSHX);
+    free(pabyBuf);
+
+    // unsigned int nCurrentRecordOffset = 0;
+    unsigned int nCurrentSHPOffset = 100;
+    unsigned int nRealSHXContentSize = 100;
+    int nRetCode = TRUE;
+    unsigned int nRecordOffset = 50;
 
-    while( nCurrentSHPOffset < nSHPFilesize )
+    while (nCurrentSHPOffset < nSHPFilesize)
     {
-        if( psHooks->FRead( &niRecord, 4, 1, fpSHP ) == 1 &&
-            psHooks->FRead( &nRecordLength, 4, 1, fpSHP ) == 1)
+        unsigned int niRecord = 0;
+        unsigned int nRecordLength = 0;
+        int nSHPType;
+
+        if (psHooks->FRead(&niRecord, 4, 1, fpSHP) == 1 &&
+            psHooks->FRead(&nRecordLength, 4, 1, fpSHP) == 1 &&
+            psHooks->FRead(&nSHPType, 4, 1, fpSHP) == 1)
         {
-            if( !bBigEndian ) SwapWord( 4, &nRecordOffset );
-            memcpy( abyReadedRecord, &nRecordOffset, 4 );
-            memcpy( abyReadedRecord + 4, &nRecordLength, 4 );
+            char abyReadRecord[8];
+            unsigned int nRecordOffsetBE = nRecordOffset;
 
-            psHooks->FWrite( abyReadedRecord, 8, 1, fpSHX );
+            if (!bBigEndian)
+                SwapWord(4, &nRecordOffsetBE);
+            memcpy(abyReadRecord, &nRecordOffsetBE, 4);
+            memcpy(abyReadRecord + 4, &nRecordLength, 4);
+
+            if (!bBigEndian)
+                SwapWord(4, &nRecordLength);
+
+            if (bBigEndian)
+                SwapWord(4, &nSHPType);
+
+            // Sanity check on record length
+            if (nRecordLength < 1 ||
+                nRecordLength > (nSHPFilesize - (nCurrentSHPOffset + 8)) / 2)
+            {
+                char szErrorMsg[200];
+                snprintf(szErrorMsg, sizeof(szErrorMsg),
+                         "Error parsing .shp to restore .shx. "
+                         "Invalid record length = %u at record starting at "
+                         "offset %u",
+                         nSHPType, nCurrentSHPOffset);
+                psHooks->Error(szErrorMsg);
+
+                nRetCode = FALSE;
+                break;
+            }
+
+            // Sanity check on record type
+            if (nSHPType != SHPT_NULL && nSHPType != SHPT_POINT &&
+                nSHPType != SHPT_ARC && nSHPType != SHPT_POLYGON &&
+                nSHPType != SHPT_MULTIPOINT && nSHPType != SHPT_POINTZ &&
+                nSHPType != SHPT_ARCZ && nSHPType != SHPT_POLYGONZ &&
+                nSHPType != SHPT_MULTIPOINTZ && nSHPType != SHPT_POINTM &&
+                nSHPType != SHPT_ARCM && nSHPType != SHPT_POLYGONM &&
+                nSHPType != SHPT_MULTIPOINTM && nSHPType != SHPT_MULTIPATCH)
+            {
+                char szErrorMsg[200];
+                snprintf(szErrorMsg, sizeof(szErrorMsg),
+                         "Error parsing .shp to restore .shx. "
+                         "Invalid shape type = %d at record starting at "
+                         "offset %u",
+                         nSHPType, nCurrentSHPOffset);
+                psHooks->Error(szErrorMsg);
+
+                nRetCode = FALSE;
+                break;
+            }
+
+            psHooks->FWrite(abyReadRecord, 8, 1, fpSHX);
 
-            if ( !bBigEndian ) SwapWord( 4, &nRecordOffset );
-            if ( !bBigEndian ) SwapWord( 4, &nRecordLength );
             nRecordOffset += nRecordLength + 4;
-            nCurrentRecordOffset += 8;
+            // nCurrentRecordOffset += 8;
             nCurrentSHPOffset += 8 + nRecordLength * 2;
 
-            psHooks->FSeek( fpSHP, nCurrentSHPOffset, 0 );
+            psHooks->FSeek(fpSHP, nCurrentSHPOffset, 0);
             nRealSHXContentSize += 8;
         }
         else
         {
-            psHooks->Error( "Error parsing .shp to restore .shx"  );
-
-            psHooks->FClose( fpSHX );
-            psHooks->FClose( fpSHP );
-
-            free( pabySHXHeader );
-            free( pszFullname );
+            char szErrorMsg[200];
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Error parsing .shp to restore .shx. "
+                     "Cannot read first bytes of record starting at "
+                     "offset %u",
+                     nCurrentSHPOffset);
+            psHooks->Error(szErrorMsg);
 
-            return( 0 );
+            nRetCode = FALSE;
+            break;
         }
     }
+    if (nRetCode && nCurrentSHPOffset != nSHPFilesize)
+    {
+        psHooks->Error("Error parsing .shp to restore .shx. "
+                       "Not expected number of bytes");
+
+        nRetCode = FALSE;
+    }
 
-    nRealSHXContentSize /= 2; // Bytes counted -> WORDs
-    if( !bBigEndian ) SwapWord( 4, &nRealSHXContentSize );
-    psHooks->FSeek( fpSHX, 24, 0 );
-    psHooks->FWrite( &nRealSHXContentSize, 4, 1, fpSHX );
+    nRealSHXContentSize /= 2;  // Bytes counted -> WORDs
+    if (!bBigEndian)
+        SwapWord(4, &nRealSHXContentSize);
+    psHooks->FSeek(fpSHX, 24, 0);
+    psHooks->FWrite(&nRealSHXContentSize, 4, 1, fpSHX);
 
-    psHooks->FClose( fpSHP );
-    psHooks->FClose( fpSHX );
+    psHooks->FClose(fpSHP);
+    psHooks->FClose(fpSHX);
 
-    free ( pabyBuf );
-    free ( pszFullname );
-    free ( pabySHXHeader );
+    free(pszFullname);
+    free(pabySHXHeader);
 
-    return( 1 );
+    return nRetCode;
 }
 
 /************************************************************************/
 /*                              SHPClose()                              */
-/*                                                                     */
-/*     Close the .shp and .shx files.                                  */
+/*                                                                      */
+/*      Close the .shp and .shx files.                                  */
 /************************************************************************/
 
-void SHPAPI_CALL
-SHPClose(SHPHandle psSHP )
-
+void SHPAPI_CALL SHPClose(SHPHandle psSHP)
 {
-    if( psSHP == SHPLIB_NULLPTR )
+    if (psSHP == SHPLIB_NULLPTR)
         return;
 
-/* -------------------------------------------------------------------- */
-/*     Update the header if we have modified anything.                 */
-/* -------------------------------------------------------------------- */
-    if( psSHP->bUpdated )
-       SHPWriteHeader( psSHP );
+    /* -------------------------------------------------------------------- */
+    /*      Update the header if we have modified anything.                 */
+    /* -------------------------------------------------------------------- */
+    if (psSHP->bUpdated)
+        SHPWriteHeader(psSHP);
 
-/* -------------------------------------------------------------------- */
-/*      Free all resources, and close files.                            */
-/* -------------------------------------------------------------------- */
-    free( psSHP->panRecOffset );
-    free( psSHP->panRecSize );
+    /* -------------------------------------------------------------------- */
+    /*      Free all resources, and close files.                            */
+    /* -------------------------------------------------------------------- */
+    free(psSHP->panRecOffset);
+    free(psSHP->panRecSize);
 
-    if ( psSHP->fpSHX != SHPLIB_NULLPTR)
-        psSHP->sHooks.FClose( psSHP->fpSHX );
-    psSHP->sHooks.FClose( psSHP->fpSHP );
+    if (psSHP->fpSHX != SHPLIB_NULLPTR)
+        psSHP->sHooks.FClose(psSHP->fpSHX);
+    psSHP->sHooks.FClose(psSHP->fpSHP);
 
-    if( psSHP->pabyRec != SHPLIB_NULLPTR )
+    if (psSHP->pabyRec != SHPLIB_NULLPTR)
     {
-        free( psSHP->pabyRec );
+        free(psSHP->pabyRec);
     }
 
-    if( psSHP->pabyObjectBuf != SHPLIB_NULLPTR )
+    if (psSHP->pabyObjectBuf != SHPLIB_NULLPTR)
     {
-        free( psSHP->pabyObjectBuf );
+        free(psSHP->pabyObjectBuf);
     }
-    if( psSHP->psCachedObject != SHPLIB_NULLPTR )
+    if (psSHP->psCachedObject != SHPLIB_NULLPTR)
     {
-        free( psSHP->psCachedObject );
+        free(psSHP->psCachedObject);
     }
 
-    free( psSHP );
+    free(psSHP);
 }
 
 /************************************************************************/
@@ -1193,14 +954,15 @@ SHPClose(SHPHandle psSHP )
 /* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
 /* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
 /* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
-void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode )
+void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode)
 {
-    if( bFastMode )
+    if (bFastMode)
     {
-        if( hSHP->psCachedObject == SHPLIB_NULLPTR )
+        if (hSHP->psCachedObject == SHPLIB_NULLPTR)
         {
-            hSHP->psCachedObject = STATIC_CAST(SHPObject*, calloc(1, sizeof(SHPObject)));
-            assert( hSHP->psCachedObject != SHPLIB_NULLPTR );
+            hSHP->psCachedObject =
+                STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+            assert(hSHP->psCachedObject != SHPLIB_NULLPTR);
         }
     }
 
@@ -1213,27 +975,23 @@ void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode )
 /*      Fetch general information about the shape file.                 */
 /************************************************************************/
 
-void SHPAPI_CALL
-SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
-           double * padfMinBound, double * padfMaxBound )
-
+void SHPAPI_CALL SHPGetInfo(SHPHandle psSHP, int *pnEntities, int *pnShapeType,
+                            double *padfMinBound, double *padfMaxBound)
 {
-    int                i;
-
-    if( psSHP == SHPLIB_NULLPTR )
+    if (psSHP == SHPLIB_NULLPTR)
         return;
 
-    if( pnEntities != SHPLIB_NULLPTR )
+    if (pnEntities != SHPLIB_NULLPTR)
         *pnEntities = psSHP->nRecords;
 
-    if( pnShapeType != SHPLIB_NULLPTR )
+    if (pnShapeType != SHPLIB_NULLPTR)
         *pnShapeType = psSHP->nShapeType;
 
-    for( i = 0; i < 4; i++ )
+    for (int i = 0; i < 4; i++)
     {
-        if( padfMinBound != SHPLIB_NULLPTR )
+        if (padfMinBound != SHPLIB_NULLPTR)
             padfMinBound[i] = psSHP->adBoundsMin[i];
-        if( padfMaxBound != SHPLIB_NULLPTR )
+        if (padfMaxBound != SHPLIB_NULLPTR)
             padfMaxBound[i] = psSHP->adBoundsMax[i];
     }
 }
@@ -1245,15 +1003,13 @@ SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
 /*      shape file with read/write access.                              */
 /************************************************************************/
 
-SHPHandle SHPAPI_CALL
-SHPCreate( const char * pszLayer, int nShapeType )
-
+SHPHandle SHPAPI_CALL SHPCreate(const char *pszLayer, int nShapeType)
 {
     SAHooks sHooks;
 
-    SASetupDefaultHooks( &sHooks );
+    SASetupDefaultHooks(&sHooks);
 
-    return SHPCreateLL( pszLayer, nShapeType, &sHooks );
+    return SHPCreateLL(pszLayer, nShapeType, &sHooks);
 }
 
 /************************************************************************/
@@ -1263,137 +1019,158 @@ SHPCreate( const char * pszLayer, int nShapeType )
 /*      shape file with read/write access.                              */
 /************************************************************************/
 
-SHPHandle SHPAPI_CALL
-SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
-
+SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
+                                  const SAHooks *psHooks)
 {
-    char       *pszFullname;
-    SAFile     fpSHP;
-    SAFile      fpSHX = SHPLIB_NULLPTR;
-    uchar      abyHeader[100];
-    int32      i32;
-    double     dValue;
-    int         nLenWithoutExtension;
-
 /* -------------------------------------------------------------------- */
 /*      Establish the byte order on this system.                        */
 /* -------------------------------------------------------------------- */
 #if !defined(bBigEndian)
     {
         int i = 1;
-        if( *((uchar *) &i) == 1 )
-            bBigEndian = FALSE;
+        if (*((unsigned char *)&i) == 1)
+            bBigEndian = false;
         else
-            bBigEndian = TRUE;
+            bBigEndian = true;
     }
 #endif
 
-/* -------------------------------------------------------------------- */
-/*      Open the two files so we can write their headers.               */
-/* -------------------------------------------------------------------- */
-    nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
-    pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+    /* -------------------------------------------------------------------- */
+    /*      Open the two files so we can write their headers.               */
+    /* -------------------------------------------------------------------- */
+    const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+    char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
     memcpy(pszFullname, pszLayer, nLenWithoutExtension);
     memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
-    fpSHP = psHooks->FOpen(pszFullname, "wb" );
-    if( fpSHP == SHPLIB_NULLPTR )
+    SAFile fpSHP = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData);
+    if (fpSHP == SHPLIB_NULLPTR)
     {
         char szErrorMsg[200];
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Failed to create file %s: %s",
-                  pszFullname, strerror(errno) );
-        psHooks->Error( szErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s",
+                 pszFullname, strerror(errno));
+        psHooks->Error(szErrorMsg);
 
-        goto error;
+        free(pszFullname);
+        return NULL;
     }
 
     memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
-    fpSHX = psHooks->FOpen(pszFullname, "wb" );
-    if( fpSHX == SHPLIB_NULLPTR )
+    SAFile fpSHX = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData);
+    if (fpSHX == SHPLIB_NULLPTR)
     {
         char szErrorMsg[200];
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Failed to create file %s: %s",
-                  pszFullname, strerror(errno) );
-        psHooks->Error( szErrorMsg );
-        goto error;
+        snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s",
+                 pszFullname, strerror(errno));
+        psHooks->Error(szErrorMsg);
+
+        free(pszFullname);
+        psHooks->FClose(fpSHP);
+        return NULL;
     }
 
-    free( pszFullname ); pszFullname = SHPLIB_NULLPTR;
+    free(pszFullname);
+    pszFullname = SHPLIB_NULLPTR;
 
-/* -------------------------------------------------------------------- */
-/*      Prepare header block for .shp file.                             */
-/* -------------------------------------------------------------------- */
-    memset( abyHeader, 0, sizeof(abyHeader) );
+    /* -------------------------------------------------------------------- */
+    /*      Prepare header block for .shp file.                             */
+    /* -------------------------------------------------------------------- */
+    unsigned char abyHeader[100];
+    memset(abyHeader, 0, sizeof(abyHeader));
 
-    abyHeader[2] = 0x27;                               /* magic cookie */
+    abyHeader[2] = 0x27; /* magic cookie */
     abyHeader[3] = 0x0a;
 
-    i32 = 50;                                          /* file size */
-    ByteCopy( &i32, abyHeader+24, 4 );
-    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    uint32_t i32 = 50; /* file size */
+    ByteCopy(&i32, abyHeader + 24, 4);
+    if (!bBigEndian)
+        SwapWord(4, abyHeader + 24);
 
-    i32 = 1000;                                                /* version */
-    ByteCopy( &i32, abyHeader+28, 4 );
-    if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+    i32 = 1000; /* version */
+    ByteCopy(&i32, abyHeader + 28, 4);
+    if (bBigEndian)
+        SwapWord(4, abyHeader + 28);
 
-    i32 = nShapeType;                                  /* shape type */
-    ByteCopy( &i32, abyHeader+32, 4 );
-    if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+    i32 = nShapeType; /* shape type */
+    ByteCopy(&i32, abyHeader + 32, 4);
+    if (bBigEndian)
+        SwapWord(4, abyHeader + 32);
 
-    dValue = 0.0;                                      /* set bounds */
-    ByteCopy( &dValue, abyHeader+36, 8 );
-    ByteCopy( &dValue, abyHeader+44, 8 );
-    ByteCopy( &dValue, abyHeader+52, 8 );
-    ByteCopy( &dValue, abyHeader+60, 8 );
+    double dValue = 0.0; /* set bounds */
+    ByteCopy(&dValue, abyHeader + 36, 8);
+    ByteCopy(&dValue, abyHeader + 44, 8);
+    ByteCopy(&dValue, abyHeader + 52, 8);
+    ByteCopy(&dValue, abyHeader + 60, 8);
 
-/* -------------------------------------------------------------------- */
-/*      Write .shp file header.                                         */
-/* -------------------------------------------------------------------- */
-    if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
+    /* -------------------------------------------------------------------- */
+    /*      Write .shp file header.                                         */
+    /* -------------------------------------------------------------------- */
+    if (psHooks->FWrite(abyHeader, 100, 1, fpSHP) != 1)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Failed to write .shp header: %s", strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psHooks->Error( szErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Failed to write .shp header: %s", strerror(errno));
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psHooks->Error(szErrorMsg);
 
-        goto error;
+        free(pszFullname);
+        psHooks->FClose(fpSHP);
+        psHooks->FClose(fpSHX);
+        return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Prepare, and write .shx file header.                            */
-/* -------------------------------------------------------------------- */
-    i32 = 50;                                          /* file size */
-    ByteCopy( &i32, abyHeader+24, 4 );
-    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    /* -------------------------------------------------------------------- */
+    /*      Prepare, and write .shx file header.                            */
+    /* -------------------------------------------------------------------- */
+    i32 = 50; /* file size */
+    ByteCopy(&i32, abyHeader + 24, 4);
+    if (!bBigEndian)
+        SwapWord(4, abyHeader + 24);
 
-    if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
+    if (psHooks->FWrite(abyHeader, 100, 1, fpSHX) != 1)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Failure writing .shx header: %s", strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psHooks->Error( szErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Failure writing .shx header: %s", strerror(errno));
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psHooks->Error(szErrorMsg);
 
-        goto error;
+        free(pszFullname);
+        psHooks->FClose(fpSHP);
+        psHooks->FClose(fpSHX);
+        return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Close the files, and then open them as regular existing files.  */
-/* -------------------------------------------------------------------- */
-    psHooks->FClose( fpSHP );
-    psHooks->FClose( fpSHX );
+    SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1));
+
+    psSHP->bUpdated = FALSE;
+    memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
 
-    return( SHPOpenLL( pszLayer, "r+b", psHooks ) );
+    psSHP->fpSHP = fpSHP;
+    psSHP->fpSHX = fpSHX;
+    psSHP->nShapeType = nShapeType;
+    psSHP->nFileSize = 100;
+    psSHP->panRecOffset =
+        STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int)));
+    psSHP->panRecSize =
+        STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int)));
 
-error:
-    if (pszFullname) free(pszFullname);
-    if (fpSHP) psHooks->FClose( fpSHP );
-    if (fpSHX) psHooks->FClose( fpSHX );
-    return SHPLIB_NULLPTR;
+    if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
+        psSHP->panRecSize == SHPLIB_NULLPTR)
+    {
+        psSHP->sHooks.Error("Not enough memory to allocate requested memory");
+        psSHP->sHooks.FClose(psSHP->fpSHP);
+        psSHP->sHooks.FClose(psSHP->fpSHX);
+        if (psSHP->panRecOffset)
+            free(psSHP->panRecOffset);
+        if (psSHP->panRecSize)
+            free(psSHP->panRecSize);
+        free(psSHP);
+        return SHPLIB_NULLPTR;
+    }
+
+    return psSHP;
 }
 
 /************************************************************************/
@@ -1403,20 +1180,19 @@ error:
 /*      indicated location in the record.                               */
 /************************************************************************/
 
-static void    _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
-
+static void _SHPSetBounds(unsigned char *pabyRec, const SHPObject *psShape)
 {
-    ByteCopy( &(psShape->dfXMin), pabyRec +  0, 8 );
-    ByteCopy( &(psShape->dfYMin), pabyRec +  8, 8 );
-    ByteCopy( &(psShape->dfXMax), pabyRec + 16, 8 );
-    ByteCopy( &(psShape->dfYMax), pabyRec + 24, 8 );
+    ByteCopy(&(psShape->dfXMin), pabyRec + 0, 8);
+    ByteCopy(&(psShape->dfYMin), pabyRec + 8, 8);
+    ByteCopy(&(psShape->dfXMax), pabyRec + 16, 8);
+    ByteCopy(&(psShape->dfYMax), pabyRec + 24, 8);
 
-    if( bBigEndian )
+    if (bBigEndian)
     {
-        SwapWord( 8, pabyRec + 0 );
-        SwapWord( 8, pabyRec + 8 );
-        SwapWord( 8, pabyRec + 16 );
-        SwapWord( 8, pabyRec + 24 );
+        SwapWord(8, pabyRec + 0);
+        SwapWord(8, pabyRec + 8);
+        SwapWord(8, pabyRec + 16);
+        SwapWord(8, pabyRec + 24);
     }
 }
 
@@ -1427,16 +1203,12 @@ static void     _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
 /*      SHPCreateObject().                                              */
 /************************************************************************/
 
-void SHPAPI_CALL
-SHPComputeExtents( SHPObject * psObject )
-
+void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject)
 {
-    int                i;
-
-/* -------------------------------------------------------------------- */
-/*      Build extents for this object.                                  */
-/* -------------------------------------------------------------------- */
-    if( psObject->nVertices > 0 )
+    /* -------------------------------------------------------------------- */
+    /*      Build extents for this object.                                  */
+    /* -------------------------------------------------------------------- */
+    if (psObject->nVertices > 0)
     {
         psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
         psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
@@ -1444,7 +1216,7 @@ SHPComputeExtents( SHPObject * psObject )
         psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
     }
 
-    for( i = 0; i < psObject->nVertices; i++ )
+    for (int i = 0; i < psObject->nVertices; i++)
     {
         psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
         psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
@@ -1466,114 +1238,114 @@ SHPComputeExtents( SHPObject * psObject )
 /************************************************************************/
 
 SHPObject SHPAPI_CALL1(*)
-SHPCreateObject( int nSHPType, int nShapeId, int nParts,
-                 const int * panPartStart, const int * panPartType,
-                 int nVertices, const double *padfX, const double *padfY,
-                 const double * padfZ, const double * padfM )
-
+    SHPCreateObject(int nSHPType, int nShapeId, int nParts,
+                    const int *panPartStart, const int *panPartType,
+                    int nVertices, const double *padfX, const double *padfY,
+                    const double *padfZ, const double *padfM)
 {
-    SHPObject  *psObject;
-    int                i, bHasM, bHasZ;
-
-    psObject = STATIC_CAST(SHPObject *, calloc(1,sizeof(SHPObject)));
+    SHPObject *psObject =
+        STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
     psObject->nSHPType = nSHPType;
     psObject->nShapeId = nShapeId;
     psObject->bMeasureIsUsed = FALSE;
 
-/* -------------------------------------------------------------------- */
-/*     Establish whether this shape type has M, and Z values.          */
-/* -------------------------------------------------------------------- */
-    if( nSHPType == SHPT_ARCM
-        || nSHPType == SHPT_POINTM
-        || nSHPType == SHPT_POLYGONM
-        || nSHPType == SHPT_MULTIPOINTM )
+    /* -------------------------------------------------------------------- */
+    /*      Establish whether this shape type has M, and Z values.          */
+    /* -------------------------------------------------------------------- */
+    bool bHasM;
+    bool bHasZ;
+
+    if (nSHPType == SHPT_ARCM || nSHPType == SHPT_POINTM ||
+        nSHPType == SHPT_POLYGONM || nSHPType == SHPT_MULTIPOINTM)
     {
-        bHasM = TRUE;
-        bHasZ = FALSE;
+        bHasM = true;
+        bHasZ = false;
     }
-    else if( nSHPType == SHPT_ARCZ
-             || nSHPType == SHPT_POINTZ
-             || nSHPType == SHPT_POLYGONZ
-             || nSHPType == SHPT_MULTIPOINTZ
-             || nSHPType == SHPT_MULTIPATCH )
+    else if (nSHPType == SHPT_ARCZ || nSHPType == SHPT_POINTZ ||
+             nSHPType == SHPT_POLYGONZ || nSHPType == SHPT_MULTIPOINTZ ||
+             nSHPType == SHPT_MULTIPATCH)
     {
-        bHasM = TRUE;
-        bHasZ = TRUE;
+        bHasM = true;
+        bHasZ = true;
     }
     else
     {
-        bHasM = FALSE;
-        bHasZ = FALSE;
+        bHasM = false;
+        bHasZ = false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Capture parts.  Note that part type is optional, and            */
-/*      defaults to ring.                                               */
-/* -------------------------------------------------------------------- */
-    if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
-        || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
-        || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
-        || nSHPType == SHPT_MULTIPATCH )
+    /* -------------------------------------------------------------------- */
+    /*      Capture parts.  Note that part type is optional, and            */
+    /*      defaults to ring.                                               */
+    /* -------------------------------------------------------------------- */
+    if (nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON ||
+        nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM ||
+        nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ ||
+        nSHPType == SHPT_MULTIPATCH)
     {
-        psObject->nParts = MAX(1,nParts);
+        psObject->nParts = MAX(1, nParts);
 
-        psObject->panPartStart = STATIC_CAST(int *,
-            calloc(sizeof(int), psObject->nParts));
-        psObject->panPartType = STATIC_CAST(int *,
-            malloc(sizeof(int) * psObject->nParts));
+        psObject->panPartStart =
+            STATIC_CAST(int *, calloc(sizeof(int), psObject->nParts));
+        psObject->panPartType =
+            STATIC_CAST(int *, malloc(sizeof(int) * psObject->nParts));
 
         psObject->panPartStart[0] = 0;
         psObject->panPartType[0] = SHPP_RING;
 
-        for( i = 0; i < nParts; i++ )
+        for (int i = 0; i < nParts; i++)
         {
-            if( panPartStart != SHPLIB_NULLPTR )
+            if (panPartStart != SHPLIB_NULLPTR)
                 psObject->panPartStart[i] = panPartStart[i];
 
-            if( panPartType != SHPLIB_NULLPTR )
+            if (panPartType != SHPLIB_NULLPTR)
                 psObject->panPartType[i] = panPartType[i];
             else
                 psObject->panPartType[i] = SHPP_RING;
         }
 
-        if( psObject->panPartStart[0] != 0 )
+        if (psObject->panPartStart[0] != 0)
             psObject->panPartStart[0] = 0;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Capture vertices.  Note that X, Y, Z and M are optional.        */
-/* -------------------------------------------------------------------- */
-    if( nVertices > 0 )
-    {
-        size_t nSize = sizeof(double) * nVertices;
-        psObject->padfX = STATIC_CAST(double *, padfX ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices));
-        psObject->padfY = STATIC_CAST(double *, padfY ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices));
-        psObject->padfZ = STATIC_CAST(double *, padfZ && bHasZ ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices));
-        psObject->padfM = STATIC_CAST(double *, padfM && bHasM ? malloc(nSize) :
-                                             calloc(sizeof(double),nVertices));
-        if( padfX != SHPLIB_NULLPTR )
+    /* -------------------------------------------------------------------- */
+    /*      Capture vertices.  Note that X, Y, Z and M are optional.        */
+    /* -------------------------------------------------------------------- */
+    if (nVertices > 0)
+    {
+        const size_t nSize = sizeof(double) * nVertices;
+        psObject->padfX =
+            STATIC_CAST(double *, padfX ? malloc(nSize)
+                                        : calloc(sizeof(double), nVertices));
+        psObject->padfY =
+            STATIC_CAST(double *, padfY ? malloc(nSize)
+                                        : calloc(sizeof(double), nVertices));
+        psObject->padfZ = STATIC_CAST(
+            double *,
+            padfZ &&bHasZ ? malloc(nSize) : calloc(sizeof(double), nVertices));
+        psObject->padfM = STATIC_CAST(
+            double *,
+            padfM &&bHasM ? malloc(nSize) : calloc(sizeof(double), nVertices));
+        if (padfX != SHPLIB_NULLPTR)
             memcpy(psObject->padfX, padfX, nSize);
-        if( padfY != SHPLIB_NULLPTR )
+        if (padfY != SHPLIB_NULLPTR)
             memcpy(psObject->padfY, padfY, nSize);
-        if( padfZ != SHPLIB_NULLPTR && bHasZ )
+        if (padfZ != SHPLIB_NULLPTR && bHasZ)
             memcpy(psObject->padfZ, padfZ, nSize);
-        if( padfM != SHPLIB_NULLPTR && bHasM )
+        if (padfM != SHPLIB_NULLPTR && bHasM)
         {
             memcpy(psObject->padfM, padfM, nSize);
             psObject->bMeasureIsUsed = TRUE;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Compute the extents.                                            */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      Compute the extents.                                            */
+    /* -------------------------------------------------------------------- */
     psObject->nVertices = nVertices;
-    SHPComputeExtents( psObject );
+    SHPComputeExtents(psObject);
 
-    return( psObject );
+    return (psObject);
 }
 
 /************************************************************************/
@@ -1584,13 +1356,11 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
 /************************************************************************/
 
 SHPObject SHPAPI_CALL1(*)
-SHPCreateSimpleObject( int nSHPType, int nVertices,
-                       const double * padfX, const double * padfY,
-                       const double * padfZ )
-
+    SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX,
+                          const double *padfY, const double *padfZ)
 {
-    return( SHPCreateObject( nSHPType, -1, 0, SHPLIB_NULLPTR, SHPLIB_NULLPTR,
-                             nVertices, padfX, padfY, padfZ, SHPLIB_NULLPTR ) );
+    return (SHPCreateObject(nSHPType, -1, 0, SHPLIB_NULLPTR, SHPLIB_NULLPTR,
+                            nVertices, padfX, padfY, padfZ, SHPLIB_NULLPTR));
 }
 
 /************************************************************************/
@@ -1600,116 +1370,141 @@ SHPCreateSimpleObject( int nSHPType, int nVertices,
 /*      only possible to write vertices at the end of the file.         */
 /************************************************************************/
 
-int SHPAPI_CALL
-SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
-
+int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId,
+                               SHPObject *psObject)
 {
-    unsigned int               nRecordOffset, nRecordSize=0;
-    int i;
-    uchar      *pabyRec;
-    int32      i32;
-    int     bAppendToLastRecord = FALSE;
-    int     bAppendToFile = FALSE;
-
     psSHP->bUpdated = TRUE;
 
-/* -------------------------------------------------------------------- */
-/*      Ensure that shape object matches the type of the file it is     */
-/*      being written to.                                               */
-/* -------------------------------------------------------------------- */
-    assert( psObject->nSHPType == psSHP->nShapeType
-            || psObject->nSHPType == SHPT_NULL );
-
-/* -------------------------------------------------------------------- */
-/*      Ensure that -1 is used for appends.  Either blow an             */
-/*      assertion, or if they are disabled, set the shapeid to -1       */
-/*      for appends.                                                    */
-/* -------------------------------------------------------------------- */
-    assert( nShapeId == -1
-            || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
-
-    if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Ensure that shape object matches the type of the file it is     */
+    /*      being written to.                                               */
+    /* -------------------------------------------------------------------- */
+    assert(psObject->nSHPType == psSHP->nShapeType ||
+           psObject->nSHPType == SHPT_NULL);
+
+    /* -------------------------------------------------------------------- */
+    /*      Ensure that -1 is used for appends.  Either blow an             */
+    /*      assertion, or if they are disabled, set the shapeid to -1       */
+    /*      for appends.                                                    */
+    /* -------------------------------------------------------------------- */
+    assert(nShapeId == -1 || (nShapeId >= 0 && nShapeId < psSHP->nRecords));
+
+    if (nShapeId != -1 && nShapeId >= psSHP->nRecords)
         nShapeId = -1;
 
-/* -------------------------------------------------------------------- */
-/*      Add the new entity to the in memory index.                      */
-/* -------------------------------------------------------------------- */
-    if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Add the new entity to the in memory index.                      */
+    /* -------------------------------------------------------------------- */
+    if (nShapeId == -1 && psSHP->nRecords + 1 > psSHP->nMaxRecords)
     {
+        /* This cannot overflow given that we check that the file size does
+         * not grow over 4 GB, and the minimum size of a record is 12 bytes,
+         * hence the maximm value for nMaxRecords is 357,913,941
+         */
         int nNewMaxRecords = psSHP->nMaxRecords + psSHP->nMaxRecords / 3 + 100;
-        unsigned intpanRecOffsetNew;
-        unsigned intpanRecSizeNew;
+        unsigned int *panRecOffsetNew;
+        unsigned int *panRecSizeNew;
 
-        panRecOffsetNew = STATIC_CAST(unsigned int *,
-            SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * nNewMaxRecords ));
-        if( panRecOffsetNew == SHPLIB_NULLPTR )
+        panRecOffsetNew = STATIC_CAST(
+            unsigned int *, realloc(psSHP->panRecOffset,
+                                    sizeof(unsigned int) * nNewMaxRecords));
+        if (panRecOffsetNew == SHPLIB_NULLPTR)
+        {
+            psSHP->sHooks.Error("Failed to write shape object. "
+                                "Memory allocation error.");
             return -1;
+        }
         psSHP->panRecOffset = panRecOffsetNew;
 
-        panRecSizeNew = STATIC_CAST(unsigned int *,
-            SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * nNewMaxRecords ));
-        if( panRecSizeNew == SHPLIB_NULLPTR )
+        panRecSizeNew = STATIC_CAST(
+            unsigned int *,
+            realloc(psSHP->panRecSize, sizeof(unsigned int) * nNewMaxRecords));
+        if (panRecSizeNew == SHPLIB_NULLPTR)
+        {
+            psSHP->sHooks.Error("Failed to write shape object. "
+                                "Memory allocation error.");
             return -1;
+        }
         psSHP->panRecSize = panRecSizeNew;
 
         psSHP->nMaxRecords = nNewMaxRecords;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize record.                                              */
-/* -------------------------------------------------------------------- */
-    pabyRec = STATIC_CAST(uchar *, malloc(psObject->nVertices * 4 * sizeof(double)
-                               + psObject->nParts * 8 + 128));
-    if( pabyRec == SHPLIB_NULLPTR )
-        return -1;
+    /* -------------------------------------------------------------------- */
+    /*      Initialize record.                                              */
+    /* -------------------------------------------------------------------- */
 
-/* -------------------------------------------------------------------- */
-/*  Extract vertices for a Polygon or Arc.                             */
-/* -------------------------------------------------------------------- */
-    if( psObject->nSHPType == SHPT_POLYGON
-        || psObject->nSHPType == SHPT_POLYGONZ
-        || psObject->nSHPType == SHPT_POLYGONM
-        || psObject->nSHPType == SHPT_ARC
-        || psObject->nSHPType == SHPT_ARCZ
-        || psObject->nSHPType == SHPT_ARCM
-        || psObject->nSHPType == SHPT_MULTIPATCH )
+    /* The following computation cannot overflow on 32-bit platforms given that
+     * the user had to allocate arrays of at least that size. */
+    size_t nRecMaxSize =
+        psObject->nVertices * 4 * sizeof(double) + psObject->nParts * 8;
+    /* But the following test could trigger on 64-bit platforms on huge
+     * geometries. */
+    const unsigned nExtraSpaceForGeomHeader = 128;
+    if (nRecMaxSize > UINT_MAX - nExtraSpaceForGeomHeader)
+    {
+        psSHP->sHooks.Error("Failed to write shape object. Too big geometry.");
+        return -1;
+    }
+    nRecMaxSize += nExtraSpaceForGeomHeader;
+    unsigned char *pabyRec = STATIC_CAST(unsigned char *, malloc(nRecMaxSize));
+    if (pabyRec == SHPLIB_NULLPTR)
     {
-        int32          nPoints, nParts;
+        psSHP->sHooks.Error("Failed to write shape object. "
+                            "Memory allocation error.");
+        return -1;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Extract vertices for a Polygon or Arc.                          */
+    /* -------------------------------------------------------------------- */
+    unsigned int nRecordSize = 0;
+    const bool bFirstFeature = psSHP->nRecords == 0;
 
-        nPoints = psObject->nVertices;
-        nParts = psObject->nParts;
+    if (psObject->nSHPType == SHPT_POLYGON ||
+        psObject->nSHPType == SHPT_POLYGONZ ||
+        psObject->nSHPType == SHPT_POLYGONM || psObject->nSHPType == SHPT_ARC ||
+        psObject->nSHPType == SHPT_ARCZ || psObject->nSHPType == SHPT_ARCM ||
+        psObject->nSHPType == SHPT_MULTIPATCH)
+    {
+        uint32_t nPoints = psObject->nVertices;
+        uint32_t nParts = psObject->nParts;
 
-        _SHPSetBounds( pabyRec + 12, psObject );
+        _SHPSetBounds(pabyRec + 12, psObject);
 
-        if( bBigEndian ) SwapWord( 4, &nPoints );
-        if( bBigEndian ) SwapWord( 4, &nParts );
+        if (bBigEndian)
+            SwapWord(4, &nPoints);
+        if (bBigEndian)
+            SwapWord(4, &nParts);
 
-        ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
-        ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
+        ByteCopy(&nPoints, pabyRec + 40 + 8, 4);
+        ByteCopy(&nParts, pabyRec + 36 + 8, 4);
 
         nRecordSize = 52;
 
         /*
          * Write part start positions.
          */
-        ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
-                  4 * psObject->nParts );
-        for( i = 0; i < psObject->nParts; i++ )
+        ByteCopy(psObject->panPartStart, pabyRec + 44 + 8,
+                 4 * psObject->nParts);
+        for (int i = 0; i < psObject->nParts; i++)
         {
-            if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
+            if (bBigEndian)
+                SwapWord(4, pabyRec + 44 + 8 + 4 * i);
             nRecordSize += 4;
         }
 
         /*
          * Write multipatch part types if needed.
          */
-        if( psObject->nSHPType == SHPT_MULTIPATCH )
+        if (psObject->nSHPType == SHPT_MULTIPATCH)
         {
-            memcpy( pabyRec + nRecordSize, psObject->panPartType,
-                    4*psObject->nParts );
-            for( i = 0; i < psObject->nParts; i++ )
+            memcpy(pabyRec + nRecordSize, psObject->panPartType,
+                   4 * psObject->nParts);
+            for (int i = 0; i < psObject->nParts; i++)
             {
-                if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
+                if (bBigEndian)
+                    SwapWord(4, pabyRec + nRecordSize);
                 nRecordSize += 4;
             }
         }
@@ -1717,16 +1512,16 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         /*
          * Write the (x,y) vertex values.
          */
-        for( i = 0; i < psObject->nVertices; i++ )
+        for (int i = 0; i < psObject->nVertices; i++)
         {
-            ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
-            ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
+            ByteCopy(psObject->padfX + i, pabyRec + nRecordSize, 8);
+            ByteCopy(psObject->padfY + i, pabyRec + nRecordSize + 8, 8);
 
-            if( bBigEndian )
-                SwapWord( 8, pabyRec + nRecordSize );
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
 
-            if( bBigEndian )
-                SwapWord( 8, pabyRec + nRecordSize + 8 );
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize + 8);
 
             nRecordSize += 2 * 8;
         }
@@ -1734,22 +1529,25 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         /*
          * Write the Z coordinates (if any).
          */
-        if( psObject->nSHPType == SHPT_POLYGONZ
-            || psObject->nSHPType == SHPT_ARCZ
-            || psObject->nSHPType == SHPT_MULTIPATCH )
+        if (psObject->nSHPType == SHPT_POLYGONZ ||
+            psObject->nSHPType == SHPT_ARCZ ||
+            psObject->nSHPType == SHPT_MULTIPATCH)
         {
-            ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            for( i = 0; i < psObject->nVertices; i++ )
+            for (int i = 0; i < psObject->nVertices; i++)
             {
-                ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
-                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8);
+                if (bBigEndian)
+                    SwapWord(8, pabyRec + nRecordSize);
                 nRecordSize += 8;
             }
         }
@@ -1757,172 +1555,190 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         /*
          * Write the M values, if any.
          */
-        if( psObject->bMeasureIsUsed
-            && (psObject->nSHPType == SHPT_POLYGONM
-                || psObject->nSHPType == SHPT_ARCM
+        if (psObject->bMeasureIsUsed &&
+            (psObject->nSHPType == SHPT_POLYGONM ||
+             psObject->nSHPType == SHPT_ARCM
 #ifndef DISABLE_MULTIPATCH_MEASURE
-                || psObject->nSHPType == SHPT_MULTIPATCH
+             || psObject->nSHPType == SHPT_MULTIPATCH
 #endif
-                || psObject->nSHPType == SHPT_POLYGONZ
-                || psObject->nSHPType == SHPT_ARCZ) )
+             || psObject->nSHPType == SHPT_POLYGONZ ||
+             psObject->nSHPType == SHPT_ARCZ))
         {
-            ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            for( i = 0; i < psObject->nVertices; i++ )
+            for (int i = 0; i < psObject->nVertices; i++)
             {
-                ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
-                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8);
+                if (bBigEndian)
+                    SwapWord(8, pabyRec + nRecordSize);
                 nRecordSize += 8;
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*  Extract vertices for a MultiPoint.                                 */
-/* -------------------------------------------------------------------- */
-    else if( psObject->nSHPType == SHPT_MULTIPOINT
-             || psObject->nSHPType == SHPT_MULTIPOINTZ
-             || psObject->nSHPType == SHPT_MULTIPOINTM )
+    /* -------------------------------------------------------------------- */
+    /*      Extract vertices for a MultiPoint.                              */
+    /* -------------------------------------------------------------------- */
+    else if (psObject->nSHPType == SHPT_MULTIPOINT ||
+             psObject->nSHPType == SHPT_MULTIPOINTZ ||
+             psObject->nSHPType == SHPT_MULTIPOINTM)
     {
-        int32          nPoints;
+        uint32_t nPoints = psObject->nVertices;
 
-        nPoints = psObject->nVertices;
+        _SHPSetBounds(pabyRec + 12, psObject);
 
-        _SHPSetBounds( pabyRec + 12, psObject );
+        if (bBigEndian)
+            SwapWord(4, &nPoints);
+        ByteCopy(&nPoints, pabyRec + 44, 4);
 
-        if( bBigEndian ) SwapWord( 4, &nPoints );
-        ByteCopy( &nPoints, pabyRec + 44, 4 );
-
-        for( i = 0; i < psObject->nVertices; i++ )
+        for (int i = 0; i < psObject->nVertices; i++)
         {
-            ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
-            ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
+            ByteCopy(psObject->padfX + i, pabyRec + 48 + i * 16, 8);
+            ByteCopy(psObject->padfY + i, pabyRec + 48 + i * 16 + 8, 8);
 
-            if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
+            if (bBigEndian)
+                SwapWord(8, pabyRec + 48 + i * 16);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + 48 + i * 16 + 8);
         }
 
         nRecordSize = 48 + 16 * psObject->nVertices;
 
-        if( psObject->nSHPType == SHPT_MULTIPOINTZ )
+        if (psObject->nSHPType == SHPT_MULTIPOINTZ)
         {
-            ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            for( i = 0; i < psObject->nVertices; i++ )
+            for (int i = 0; i < psObject->nVertices; i++)
             {
-                ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
-                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8);
+                if (bBigEndian)
+                    SwapWord(8, pabyRec + nRecordSize);
                 nRecordSize += 8;
             }
         }
 
-        if( psObject->bMeasureIsUsed
-            && (psObject->nSHPType == SHPT_MULTIPOINTZ
-                || psObject->nSHPType == SHPT_MULTIPOINTM) )
+        if (psObject->bMeasureIsUsed &&
+            (psObject->nSHPType == SHPT_MULTIPOINTZ ||
+             psObject->nSHPType == SHPT_MULTIPOINTM))
         {
-            ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
 
-            for( i = 0; i < psObject->nVertices; i++ )
+            for (int i = 0; i < psObject->nVertices; i++)
             {
-                ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
-                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8);
+                if (bBigEndian)
+                    SwapWord(8, pabyRec + nRecordSize);
                 nRecordSize += 8;
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write point.                                                   */
-/* -------------------------------------------------------------------- */
-    else if( psObject->nSHPType == SHPT_POINT
-             || psObject->nSHPType == SHPT_POINTZ
-             || psObject->nSHPType == SHPT_POINTM )
+    /* -------------------------------------------------------------------- */
+    /*      Write point.                                                    */
+    /* -------------------------------------------------------------------- */
+    else if (psObject->nSHPType == SHPT_POINT ||
+             psObject->nSHPType == SHPT_POINTZ ||
+             psObject->nSHPType == SHPT_POINTM)
     {
-        ByteCopy( psObject->padfX, pabyRec + 12, 8 );
-        ByteCopy( psObject->padfY, pabyRec + 20, 8 );
+        ByteCopy(psObject->padfX, pabyRec + 12, 8);
+        ByteCopy(psObject->padfY, pabyRec + 20, 8);
 
-        if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
-        if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
+        if (bBigEndian)
+            SwapWord(8, pabyRec + 12);
+        if (bBigEndian)
+            SwapWord(8, pabyRec + 20);
 
         nRecordSize = 28;
 
-        if( psObject->nSHPType == SHPT_POINTZ )
+        if (psObject->nSHPType == SHPT_POINTZ)
         {
-            ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(psObject->padfZ, pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
         }
 
-        if( psObject->bMeasureIsUsed
-            && (psObject->nSHPType == SHPT_POINTZ
-                || psObject->nSHPType == SHPT_POINTM) )
+        if (psObject->bMeasureIsUsed && (psObject->nSHPType == SHPT_POINTZ ||
+                                         psObject->nSHPType == SHPT_POINTM))
         {
-            ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
-            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            ByteCopy(psObject->padfM, pabyRec + nRecordSize, 8);
+            if (bBigEndian)
+                SwapWord(8, pabyRec + nRecordSize);
             nRecordSize += 8;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Not much to do for null geometries.                             */
-/* -------------------------------------------------------------------- */
-    else if( psObject->nSHPType == SHPT_NULL )
+    /* -------------------------------------------------------------------- */
+    /*      Not much to do for null geometries.                             */
+    /* -------------------------------------------------------------------- */
+    else if (psObject->nSHPType == SHPT_NULL)
     {
         nRecordSize = 12;
     }
-
     else
     {
         /* unknown type */
-        assert( FALSE );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Establish where we are going to put this record. If we are      */
-/*      rewriting the last record of the file, then we can update it in */
-/*      place. Otherwise if rewriting an existing record, and it will   */
-/*      fit, then put it  back where the original came from.  Otherwise */
-/*      write at the end.                                               */
-/* -------------------------------------------------------------------- */
-    if( nShapeId != -1 && psSHP->panRecOffset[nShapeId] +
-                        psSHP->panRecSize[nShapeId] + 8 == psSHP->nFileSize )
+        assert(false);
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Establish where we are going to put this record. If we are      */
+    /*      rewriting the last record of the file, then we can update it in */
+    /*      place. Otherwise if rewriting an existing record, and it will   */
+    /*      fit, then put it  back where the original came from.  Otherwise */
+    /*      write at the end.                                               */
+    /* -------------------------------------------------------------------- */
+    SAOffset nRecordOffset;
+    bool bAppendToLastRecord = false;
+    bool bAppendToFile = false;
+    if (nShapeId != -1 &&
+        psSHP->panRecOffset[nShapeId] + psSHP->panRecSize[nShapeId] + 8 ==
+            psSHP->nFileSize)
     {
         nRecordOffset = psSHP->panRecOffset[nShapeId];
-        bAppendToLastRecord = TRUE;
+        bAppendToLastRecord = true;
     }
-    else if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
+    else if (nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize - 8)
     {
-        ifpsSHP->nFileSize > UINT_MAX - nRecordSize)
+        if (psSHP->nFileSize > UINT_MAX - nRecordSize)
         {
-            char str[128];
-            snprintf( str, sizeof(str), "Failed to write shape object. "
-                     "File size cannot reach %u + %u.",
-                     psSHP->nFileSize, nRecordSize );
-            str[sizeof(str)-1] = '\0';
-            psSHP->sHooks.Error( str );
-            free( pabyRec );
+            char str[255];
+            snprintf(str, sizeof(str),
+                     "Failed to write shape object. "
+                     "The maximum file size of %u has been reached. "
+                     "The current record of size %u cannot be added.",
+                     psSHP->nFileSize, nRecordSize);
+            str[sizeof(str) - 1] = '\0';
+            psSHP->sHooks.Error(str);
+            free(pabyRec);
             return -1;
         }
 
-        bAppendToFile = TRUE;
+        bAppendToFile = true;
         nRecordOffset = psSHP->nFileSize;
     }
     else
@@ -1930,76 +1746,87 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         nRecordOffset = psSHP->panRecOffset[nShapeId];
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set the shape type, record number, and record size.             */
-/* -------------------------------------------------------------------- */
-    i32 = (nShapeId < 0) ? psSHP->nRecords+1 : nShapeId+1;                                     /* record # */
-    if( !bBigEndian ) SwapWord( 4, &i32 );
-    ByteCopy( &i32, pabyRec, 4 );
+    /* -------------------------------------------------------------------- */
+    /*      Set the shape type, record number, and record size.             */
+    /* -------------------------------------------------------------------- */
+    uint32_t i32 =
+        (nShapeId < 0) ? psSHP->nRecords + 1 : nShapeId + 1; /* record # */
+    if (!bBigEndian)
+        SwapWord(4, &i32);
+    ByteCopy(&i32, pabyRec, 4);
 
-    i32 = (nRecordSize-8)/2;                           /* record size */
-    if( !bBigEndian ) SwapWord( 4, &i32 );
-    ByteCopy( &i32, pabyRec + 4, 4 );
+    i32 = (nRecordSize - 8) / 2; /* record size */
+    if (!bBigEndian)
+        SwapWord(4, &i32);
+    ByteCopy(&i32, pabyRec + 4, 4);
 
-    i32 = psObject->nSHPType;                          /* shape type */
-    if( bBigEndian ) SwapWord( 4, &i32 );
-    ByteCopy( &i32, pabyRec + 8, 4 );
+    i32 = psObject->nSHPType; /* shape type */
+    if (bBigEndian)
+        SwapWord(4, &i32);
+    ByteCopy(&i32, pabyRec + 8, 4);
 
-/* -------------------------------------------------------------------- */
-/*      Write out record.                                               */
-/* -------------------------------------------------------------------- */
-    if( psSHP->sHooks.FSeek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 )
+    /* -------------------------------------------------------------------- */
+    /*      Write out record.                                               */
+    /* -------------------------------------------------------------------- */
+
+    /* -------------------------------------------------------------------- */
+    /*      Guard FSeek with check for whether we're already at position;   */
+    /*      no-op FSeeks defeat network filesystems' write buffering.       */
+    /* -------------------------------------------------------------------- */
+    if (psSHP->sHooks.FTell(psSHP->fpSHP) != nRecordOffset)
     {
-        char szErrorMsg[200];
+        if (psSHP->sHooks.FSeek(psSHP->fpSHP, nRecordOffset, 0) != 0)
+        {
+            char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Error in psSHP->sHooks.FSeek() while writing object to .shp file: %s",
-                  strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Error in psSHP->sHooks.FSeek() while writing object to "
+                     ".shp file: %s",
+                     strerror(errno));
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
 
-        free( pabyRec );
-        return -1;
+            free(pabyRec);
+            return -1;
+        }
     }
-    if( psSHP->sHooks.FWrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
+    if (psSHP->sHooks.FWrite(pabyRec, nRecordSize, 1, psSHP->fpSHP) < 1)
     {
         char szErrorMsg[200];
 
-        snprintf( szErrorMsg, sizeof(szErrorMsg),
-                 "Error in psSHP->sHooks.FWrite() while writing object of %u bytes to .shp file: %s",
-                  nRecordSize, strerror(errno) );
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Error in psSHP->sHooks.FWrite() while writing object of %u "
+                 "bytes to .shp file: %s",
+                 nRecordSize, strerror(errno));
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
 
-        free( pabyRec );
+        free(pabyRec);
         return -1;
     }
 
-    free( pabyRec );
+    free(pabyRec);
 
-    if( bAppendToLastRecord )
+    if (bAppendToLastRecord)
     {
-        psSHP->nFileSize = psSHP->panRecOffset[nShapeId] + nRecordSize; 
+        psSHP->nFileSize = psSHP->panRecOffset[nShapeId] + nRecordSize;
     }
-    else if( bAppendToFile )
+    else if (bAppendToFile)
     {
-        if( nShapeId == -1 )
+        if (nShapeId == -1)
             nShapeId = psSHP->nRecords++;
 
         psSHP->panRecOffset[nShapeId] = psSHP->nFileSize;
         psSHP->nFileSize += nRecordSize;
     }
-    psSHP->panRecSize[nShapeId] = nRecordSize-8;
+    psSHP->panRecSize[nShapeId] = nRecordSize - 8;
 
-/* -------------------------------------------------------------------- */
-/*     Expand file wide bounds based on this shape.                    */
-/* -------------------------------------------------------------------- */
-    if( psSHP->adBoundsMin[0] == 0.0
-        && psSHP->adBoundsMax[0] == 0.0
-        && psSHP->adBoundsMin[1] == 0.0
-        && psSHP->adBoundsMax[1] == 0.0 )
+    /* -------------------------------------------------------------------- */
+    /*      Expand file wide bounds based on this shape.                    */
+    /* -------------------------------------------------------------------- */
+    if (bFirstFeature)
     {
-        if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 )
+        if (psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0)
         {
             psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0;
             psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0;
@@ -2010,45 +1837,49 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         {
             psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
             psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
-            psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ ? psObject->padfZ[0] : 0.0;
-            psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM ? psObject->padfM[0] : 0.0;
+            psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] =
+                psObject->padfZ ? psObject->padfZ[0] : 0.0;
+            psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] =
+                psObject->padfM ? psObject->padfM[0] : 0.0;
         }
     }
 
-    for( i = 0; i < psObject->nVertices; i++ )
+    for (int i = 0; i < psObject->nVertices; i++)
     {
-        psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
-        psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
-        psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
-        psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
-        if( psObject->padfZ )
+        psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0], psObject->padfX[i]);
+        psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1], psObject->padfY[i]);
+        psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0], psObject->padfX[i]);
+        psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1], psObject->padfY[i]);
+        if (psObject->padfZ)
         {
-            psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
-            psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
+            psSHP->adBoundsMin[2] =
+                MIN(psSHP->adBoundsMin[2], psObject->padfZ[i]);
+            psSHP->adBoundsMax[2] =
+                MAX(psSHP->adBoundsMax[2], psObject->padfZ[i]);
         }
-        if( psObject->padfM )
+        if (psObject->padfM)
         {
-            psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
-            psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
+            psSHP->adBoundsMin[3] =
+                MIN(psSHP->adBoundsMin[3], psObject->padfM[i]);
+            psSHP->adBoundsMax[3] =
+                MAX(psSHP->adBoundsMax[3], psObject->padfM[i]);
         }
     }
 
-    return( nShapeId  );
+    return (nShapeId);
 }
 
 /************************************************************************/
 /*                         SHPAllocBuffer()                             */
 /************************************************************************/
 
-static void* SHPAllocBuffer(unsigned char** pBuffer, int nSize)
+static void *SHPAllocBuffer(unsigned char **pBuffer, int nSize)
 {
-    unsigned char* pRet;
-
-    if( pBuffer == SHPLIB_NULLPTR )
+    if (pBuffer == SHPLIB_NULLPTR)
         return calloc(1, nSize);
 
-    pRet = *pBuffer;
-    if( pRet == SHPLIB_NULLPTR )
+    unsigned char *pRet = *pBuffer;
+    if (pRet == SHPLIB_NULLPTR)
         return SHPLIB_NULLPTR;
 
     (*pBuffer) += nSize;
@@ -2059,108 +1890,106 @@ static void* SHPAllocBuffer(unsigned char** pBuffer, int nSize)
 /*                    SHPReallocObjectBufIfNecessary()                  */
 /************************************************************************/
 
-static unsigned char* SHPReallocObjectBufIfNecessary ( SHPHandle psSHP,
-                                                       int nObjectBufSize )
+static unsigned char *SHPReallocObjectBufIfNecessary(SHPHandle psSHP,
+                                                     int nObjectBufSize)
 {
-    unsigned char* pBuffer;
-    if( nObjectBufSize == 0 )
+    if (nObjectBufSize == 0)
     {
         nObjectBufSize = 4 * sizeof(double);
     }
-    if( nObjectBufSize > psSHP->nObjectBufSize )
+
+    unsigned char *pBuffer;
+    if (nObjectBufSize > psSHP->nObjectBufSize)
     {
-        pBuffer = STATIC_CAST(unsigned char*, realloc( psSHP->pabyObjectBuf, nObjectBufSize ));
-        if( pBuffer != SHPLIB_NULLPTR )
+        pBuffer = STATIC_CAST(unsigned char *,
+                              realloc(psSHP->pabyObjectBuf, nObjectBufSize));
+        if (pBuffer != SHPLIB_NULLPTR)
         {
             psSHP->pabyObjectBuf = pBuffer;
             psSHP->nObjectBufSize = nObjectBufSize;
         }
     }
     else
+    {
         pBuffer = psSHP->pabyObjectBuf;
+    }
+
     return pBuffer;
 }
 
 /************************************************************************/
 /*                          SHPReadObject()                             */
 /*                                                                      */
-/*      Read the vertices, parts, and other non-attribute information  */
-/*     for one shape.                                                  */
+/*      Read the vertices, parts, and other non-attribute information   */
+/*      for one shape.                                                  */
 /************************************************************************/
 
-SHPObject SHPAPI_CALL1(*)
-SHPReadObject( SHPHandle psSHP, int hEntity )
-
+SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity)
 {
-    int                  nEntitySize, nRequiredSize;
-    SHPObject           *psShape;
-    char                 szErrorMsg[128];
-    int                  nSHPType;
-    int                  nBytesRead;
-
-/* -------------------------------------------------------------------- */
-/*      Validate the record/entity number.                              */
-/* -------------------------------------------------------------------- */
-    if( hEntity < 0 || hEntity >= psSHP->nRecords )
+    /* -------------------------------------------------------------------- */
+    /*      Validate the record/entity number.                              */
+    /* -------------------------------------------------------------------- */
+    if (hEntity < 0 || hEntity >= psSHP->nRecords)
         return SHPLIB_NULLPTR;
 
-/* -------------------------------------------------------------------- */
-/*      Read offset/length from SHX loading if necessary.               */
-/* -------------------------------------------------------------------- */
-    if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX != SHPLIB_NULLPTR )
+    /* -------------------------------------------------------------------- */
+    /*      Read offset/length from SHX loading if necessary.               */
+    /* -------------------------------------------------------------------- */
+    if (psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX != SHPLIB_NULLPTR)
     {
-        unsigned int       nOffset, nLength;
+        unsigned int nOffset;
+        unsigned int nLength;
 
-        if( psSHP->sHooks.FSeek( psSHP->fpSHX, 100 + 8 * hEntity, 0 ) != 0 ||
-            psSHP->sHooks.FRead( &nOffset, 1, 4, psSHP->fpSHX ) != 4 ||
-            psSHP->sHooks.FRead( &nLength, 1, 4, psSHP->fpSHX ) != 4 )
+        if (psSHP->sHooks.FSeek(psSHP->fpSHX, 100 + 8 * hEntity, 0) != 0 ||
+            psSHP->sHooks.FRead(&nOffset, 1, 4, psSHP->fpSHX) != 4 ||
+            psSHP->sHooks.FRead(&nLength, 1, 4, psSHP->fpSHX) != 4)
         {
             char str[128];
-            snprintf( str, sizeof(str),
-                    "Error in fseek()/fread() reading object from .shx file at offset %d",
-                    100 + 8 * hEntity);
-            str[sizeof(str)-1] = '\0';
+            snprintf(str, sizeof(str),
+                     "Error in fseek()/fread() reading object from .shx file "
+                     "at offset %d",
+                     100 + 8 * hEntity);
+            str[sizeof(str) - 1] = '\0';
 
-            psSHP->sHooks.Error( str );
+            psSHP->sHooks.Error(str);
             return SHPLIB_NULLPTR;
         }
-        if( !bBigEndian ) SwapWord( 4, &nOffset );
-        if( !bBigEndian ) SwapWord( 4, &nLength );
+        if (!bBigEndian)
+            SwapWord(4, &nOffset);
+        if (!bBigEndian)
+            SwapWord(4, &nLength);
 
-        if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
+        if (nOffset > STATIC_CAST(unsigned int, INT_MAX))
         {
             char str[128];
-            snprintf( str, sizeof(str),
-                    "Invalid offset for entity %d", hEntity);
-            str[sizeof(str)-1] = '\0';
+            snprintf(str, sizeof(str), "Invalid offset for entity %d", hEntity);
+            str[sizeof(str) - 1] = '\0';
 
-            psSHP->sHooks.Error( str );
+            psSHP->sHooks.Error(str);
             return SHPLIB_NULLPTR;
         }
-        if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
+        if (nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4))
         {
             char str[128];
-            snprintf( str, sizeof(str),
-                    "Invalid length for entity %d", hEntity);
-            str[sizeof(str)-1] = '\0';
+            snprintf(str, sizeof(str), "Invalid length for entity %d", hEntity);
+            str[sizeof(str) - 1] = '\0';
 
-            psSHP->sHooks.Error( str );
+            psSHP->sHooks.Error(str);
             return SHPLIB_NULLPTR;
         }
 
-        psSHP->panRecOffset[hEntity] = nOffset*2;
-        psSHP->panRecSize[hEntity] = nLength*2;
+        psSHP->panRecOffset[hEntity] = nOffset * 2;
+        psSHP->panRecSize[hEntity] = nLength * 2;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Ensure our record buffer is large enough.                       */
-/* -------------------------------------------------------------------- */
-    nEntitySize = psSHP->panRecSize[hEntity]+8;
-    if( nEntitySize > psSHP->nBufSize )
+    /* -------------------------------------------------------------------- */
+    /*      Ensure our record buffer is large enough.                       */
+    /* -------------------------------------------------------------------- */
+    const int nEntitySize = psSHP->panRecSize[hEntity] + 8;
+    if (nEntitySize > psSHP->nBufSize)
     {
-        uchar* pabyRecNew;
         int nNewBufSize = nEntitySize;
-        if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
+        if (nNewBufSize < INT_MAX - nNewBufSize / 3)
             nNewBufSize += nNewBufSize / 3;
         else
             nNewBufSize = INT_MAX;
@@ -2168,45 +1997,51 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         /* Before allocating too much memory, check that the file is big enough */
         /* and do not trust the file size in the header the first time we */
         /* need to allocate more than 10 MB */
-        if( nNewBufSize >= 10 * 1024 * 1024 )
+        if (nNewBufSize >= 10 * 1024 * 1024)
         {
-            if( psSHP->nBufSize < 10 * 1024 * 1024 )
+            if (psSHP->nBufSize < 10 * 1024 * 1024)
             {
                 SAOffset nFileSize;
-                psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
+                psSHP->sHooks.FSeek(psSHP->fpSHP, 0, 2);
                 nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
-                if( nFileSize >= UINT_MAX )
+                if (nFileSize >= UINT_MAX)
                     psSHP->nFileSize = UINT_MAX;
                 else
                     psSHP->nFileSize = STATIC_CAST(unsigned int, nFileSize);
             }
 
-            ifpsSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
+            if (psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
                 /* We should normally use nEntitySize instead of*/
                 /* psSHP->panRecSize[hEntity] in the below test, but because of */
                 /* the case of non conformant .shx files detailed a bit below, */
                 /* let be more tolerant */
-                psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
+                psSHP->panRecSize[hEntity] >
+                    psSHP->nFileSize - psSHP->panRecOffset[hEntity])
             {
                 char str[128];
-                snprintf( str, sizeof(str),
-                            "Error in fread() reading object of size %d at offset %u from .shp file",
-                            nEntitySize, psSHP->panRecOffset[hEntity] );
-                str[sizeof(str)-1] = '\0';
+                snprintf(str, sizeof(str),
+                         "Error in fread() reading object of size %d at offset "
+                         "%u from .shp file",
+                         nEntitySize, psSHP->panRecOffset[hEntity]);
+                str[sizeof(str) - 1] = '\0';
 
-                psSHP->sHooks.Error( str );
+                psSHP->sHooks.Error(str);
                 return SHPLIB_NULLPTR;
             }
         }
 
-        pabyRecNew = STATIC_CAST(uchar *, SfRealloc(psSHP->pabyRec,nNewBufSize));
+        unsigned char *pabyRecNew =
+            STATIC_CAST(unsigned char *, realloc(psSHP->pabyRec, nNewBufSize));
         if (pabyRecNew == SHPLIB_NULLPTR)
         {
-            snprintf( szErrorMsg, sizeof(szErrorMsg),
-                     "Not enough memory to allocate requested memory (nNewBufSize=%d). "
-                     "Probably broken SHP file", nNewBufSize);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+            char szErrorMsg[160];
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Not enough memory to allocate requested memory "
+                     "(nNewBufSize=%d). "
+                     "Probably broken SHP file",
+                     nNewBufSize);
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             return SHPLIB_NULLPTR;
         }
 
@@ -2221,26 +2056,27 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         return SHPLIB_NULLPTR;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the record.                                                */
-/* -------------------------------------------------------------------- */
-    if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 )
+    /* -------------------------------------------------------------------- */
+    /*      Read the record.                                                */
+    /* -------------------------------------------------------------------- */
+    if (psSHP->sHooks.FSeek(psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0) != 0)
     {
         /*
          * TODO - mloskot: Consider detailed diagnostics of shape file,
          * for example to detect if file is truncated.
          */
         char str[128];
-        snprintf( str, sizeof(str),
+        snprintf(str, sizeof(str),
                  "Error in fseek() reading object from .shp file at offset %u",
                  psSHP->panRecOffset[hEntity]);
-        str[sizeof(str)-1] = '\0';
+        str[sizeof(str) - 1] = '\0';
 
-        psSHP->sHooks.Error( str );
+        psSHP->sHooks.Error(str);
         return SHPLIB_NULLPTR;
     }
 
-    nBytesRead = STATIC_CAST(int, psSHP->sHooks.FRead( psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP ));
+    const int nBytesRead = STATIC_CAST(
+        int, psSHP->sHooks.FRead(psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP));
 
     /* Special case for a shapefile whose .shx content length field is not equal */
     /* to the content length field of the .shp, which is a violation of "The */
@@ -2248,64 +2084,70 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     /* file record header." (http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf, page 24) */
     /* Actually in that case the .shx content length is equal to the .shp content length + */
     /* 4 (16 bit words), representing the 8 bytes of the record header... */
-    if( nBytesRead >= 8 && nBytesRead == nEntitySize - 8 )
+    if (nBytesRead >= 8 && nBytesRead == nEntitySize - 8)
     {
         /* Do a sanity check */
         int nSHPContentLength;
-        memcpy( &nSHPContentLength, psSHP->pabyRec + 4, 4 );
-        if( !bBigEndian ) SwapWord( 4, &(nSHPContentLength) );
-        if( nSHPContentLength < 0 ||
-            nSHPContentLength > INT_MAX / 2 - 4 ||
-            2 * nSHPContentLength + 8 != nBytesRead )
+        memcpy(&nSHPContentLength, psSHP->pabyRec + 4, 4);
+        if (!bBigEndian)
+            SwapWord(4, &(nSHPContentLength));
+        if (nSHPContentLength < 0 || nSHPContentLength > INT_MAX / 2 - 4 ||
+            2 * nSHPContentLength + 8 != nBytesRead)
         {
             char str[128];
-            snprintf( str, sizeof(str),
-                    "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
-                    hEntity );
-            str[sizeof(str)-1] = '\0';
+            snprintf(str, sizeof(str),
+                     "Sanity check failed when trying to recover from "
+                     "inconsistent .shx/.shp with shape %d",
+                     hEntity);
+            str[sizeof(str) - 1] = '\0';
 
-            psSHP->sHooks.Error( str );
+            psSHP->sHooks.Error(str);
             return SHPLIB_NULLPTR;
         }
     }
-    else if( nBytesRead != nEntitySize )
+    else if (nBytesRead != nEntitySize)
     {
         /*
          * TODO - mloskot: Consider detailed diagnostics of shape file,
          * for example to detect if file is truncated.
          */
         char str[128];
-        snprintf( str, sizeof(str),
-                 "Error in fread() reading object of size %d at offset %u from .shp file",
-                 nEntitySize, psSHP->panRecOffset[hEntity] );
-        str[sizeof(str)-1] = '\0';
+        snprintf(str, sizeof(str),
+                 "Error in fread() reading object of size %d at offset %u from "
+                 ".shp file",
+                 nEntitySize, psSHP->panRecOffset[hEntity]);
+        str[sizeof(str) - 1] = '\0';
 
-        psSHP->sHooks.Error( str );
+        psSHP->sHooks.Error(str);
         return SHPLIB_NULLPTR;
     }
 
-    if ( 8 + 4 > nEntitySize )
+    if (8 + 4 > nEntitySize)
     {
+        char szErrorMsg[160];
         snprintf(szErrorMsg, sizeof(szErrorMsg),
-                 "Corrupted .shp file : shape %d : nEntitySize = %d",
-                 hEntity, nEntitySize);
-        szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-        psSHP->sHooks.Error( szErrorMsg );
+                 "Corrupted .shp file : shape %d : nEntitySize = %d", hEntity,
+                 nEntitySize);
+        szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+        psSHP->sHooks.Error(szErrorMsg);
         return SHPLIB_NULLPTR;
     }
-    memcpy( &nSHPType, psSHP->pabyRec + 8, 4 );
+    int nSHPType;
+    memcpy(&nSHPType, psSHP->pabyRec + 8, 4);
 
-    if( bBigEndian ) SwapWord( 4, &(nSHPType) );
+    if (bBigEndian)
+        SwapWord(4, &(nSHPType));
 
-/* -------------------------------------------------------------------- */
-/*     Allocate and minimally initialize the object.                   */
-/* -------------------------------------------------------------------- */
-    if( psSHP->bFastModeReadObject )
+    /* -------------------------------------------------------------------- */
+    /*      Allocate and minimally initialize the object.                   */
+    /* -------------------------------------------------------------------- */
+    SHPObject *psShape;
+    if (psSHP->bFastModeReadObject)
     {
-        if( psSHP->psCachedObject->bFastModeReadObject )
+        if (psSHP->psCachedObject->bFastModeReadObject)
         {
-            psSHP->sHooks.Error( "Invalid read pattern in fast read mode. "
-                                 "SHPDestroyObject() should be called." );
+            psSHP->sHooks.Error("Invalid read pattern in fast read mode. "
+                                "SHPDestroyObject() should be called.");
             return SHPLIB_NULLPTR;
         }
 
@@ -2313,69 +2155,74 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         memset(psShape, 0, sizeof(SHPObject));
     }
     else
-        psShape = STATIC_CAST(SHPObject *, calloc(1,sizeof(SHPObject)));
+    {
+        psShape = STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+    }
     psShape->nShapeId = hEntity;
     psShape->nSHPType = nSHPType;
     psShape->bMeasureIsUsed = FALSE;
     psShape->bFastModeReadObject = psSHP->bFastModeReadObject;
 
-/* ==================================================================== */
-/*  Extract vertices for a Polygon or Arc.                             */
-/* ==================================================================== */
-    if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
-        || psShape->nSHPType == SHPT_POLYGONZ
-        || psShape->nSHPType == SHPT_POLYGONM
-        || psShape->nSHPType == SHPT_ARCZ
-        || psShape->nSHPType == SHPT_ARCM
-        || psShape->nSHPType == SHPT_MULTIPATCH )
+    /* ==================================================================== */
+    /*  Extract vertices for a Polygon or Arc.                              */
+    /* ==================================================================== */
+    if (psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC ||
+        psShape->nSHPType == SHPT_POLYGONZ ||
+        psShape->nSHPType == SHPT_POLYGONM || psShape->nSHPType == SHPT_ARCZ ||
+        psShape->nSHPType == SHPT_ARCM || psShape->nSHPType == SHPT_MULTIPATCH)
     {
-        int32          nPoints, nParts;
-        int                    i, nOffset;
-        unsigned char* pBuffer = SHPLIB_NULLPTR;
-        unsigned char** ppBuffer = SHPLIB_NULLPTR;
-
-        if ( 40 + 8 + 4 > nEntitySize )
+        if (40 + 8 + 4 > nEntitySize)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nEntitySize = %d",
                      hEntity, nEntitySize);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
-/* -------------------------------------------------------------------- */
-/*     Get the X/Y bounds.                                             */
-/* -------------------------------------------------------------------- */
-        memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
-        memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
-        memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
-        memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
-
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
-
-/* -------------------------------------------------------------------- */
-/*      Extract part/point count, and build vertex and part arrays      */
-/*      to proper size.                                                 */
-/* -------------------------------------------------------------------- */
-        memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
-        memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
-
-        if( bBigEndian ) SwapWord( 4, &nPoints );
-        if( bBigEndian ) SwapWord( 4, &nParts );
+        /* -------------------------------------------------------------------- */
+        /*      Get the X/Y bounds.                                             */
+        /* -------------------------------------------------------------------- */
+        memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8);
+        memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8);
+        memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8);
+        memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8);
+
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfXMin));
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfYMin));
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfXMax));
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfYMax));
+
+        /* -------------------------------------------------------------------- */
+        /*      Extract part/point count, and build vertex and part arrays      */
+        /*      to proper size.                                                 */
+        /* -------------------------------------------------------------------- */
+        uint32_t nPoints;
+        memcpy(&nPoints, psSHP->pabyRec + 40 + 8, 4);
+        uint32_t nParts;
+        memcpy(&nParts, psSHP->pabyRec + 36 + 8, 4);
+
+        if (bBigEndian)
+            SwapWord(4, &nPoints);
+        if (bBigEndian)
+            SwapWord(4, &nParts);
 
         /* nPoints and nParts are unsigned */
         if (/* nPoints < 0 || nParts < 0 || */
             nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
                      hEntity, nPoints, nParts);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
@@ -2383,44 +2230,56 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         /* With the previous checks on nPoints and nParts, */
         /* we should not overflow here and after */
         /* since 50 M * (16 + 8 + 8) = 1 600 MB */
-        nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
-        if ( psShape->nSHPType == SHPT_POLYGONZ
-             || psShape->nSHPType == SHPT_ARCZ
-             || psShape->nSHPType == SHPT_MULTIPATCH )
+        int nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
+        if (psShape->nSHPType == SHPT_POLYGONZ ||
+            psShape->nSHPType == SHPT_ARCZ ||
+            psShape->nSHPType == SHPT_MULTIPATCH)
         {
             nRequiredSize += 16 + 8 * nPoints;
         }
-        if( psShape->nSHPType == SHPT_MULTIPATCH )
+        if (psShape->nSHPType == SHPT_MULTIPATCH)
         {
             nRequiredSize += 4 * nParts;
         }
         if (nRequiredSize > nEntitySize)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, nEntitySize=%d.",
+                     "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, "
+                     "nEntitySize=%d.",
                      hEntity, nPoints, nParts, nEntitySize);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
 
-        if( psShape->bFastModeReadObject )
+        unsigned char *pBuffer = SHPLIB_NULLPTR;
+        unsigned char **ppBuffer = SHPLIB_NULLPTR;
+
+        if (psShape->bFastModeReadObject)
         {
-            int nObjectBufSize = 4 * sizeof(double) * nPoints + 2 * sizeof(int) * nParts;
+            const int nObjectBufSize =
+                4 * sizeof(double) * nPoints + 2 * sizeof(int) * nParts;
             pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
             ppBuffer = &pBuffer;
         }
 
         psShape->nVertices = nPoints;
-        psShape->padfX = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
-        psShape->padfY = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
-        psShape->padfZ = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
-        psShape->padfM = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfX = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfY = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfZ = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfM = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
 
         psShape->nParts = nParts;
-        psShape->panPartStart = STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
-        psShape->panPartType = STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
+        psShape->panPartStart =
+            STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
+        psShape->panPartType =
+            STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
 
         if (psShape->padfX == SHPLIB_NULLPTR ||
             psShape->padfY == SHPLIB_NULLPTR ||
@@ -2429,308 +2288,346 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             psShape->panPartStart == SHPLIB_NULLPTR ||
             psShape->panPartType == SHPLIB_NULLPTR)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                    "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
-                    "Probably broken SHP file", nPoints, nParts, hEntity );
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+                     "Not enough memory to allocate requested memory "
+                     "(nPoints=%u, nParts=%u) for shape %d. "
+                     "Probably broken SHP file",
+                     nPoints, nParts, hEntity);
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
 
-        for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
+        for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
             psShape->panPartType[i] = SHPP_RING;
 
-/* -------------------------------------------------------------------- */
-/*      Copy out the part array from the record.                        */
-/* -------------------------------------------------------------------- */
-        memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
-        for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
+        /* -------------------------------------------------------------------- */
+        /*      Copy out the part array from the record.                        */
+        /* -------------------------------------------------------------------- */
+        memcpy(psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts);
+        for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
         {
-            if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+            if (bBigEndian)
+                SwapWord(4, psShape->panPartStart + i);
 
             /* We check that the offset is inside the vertex array */
-            if (psShape->panPartStart[i] < 0
-                || (psShape->panPartStart[i] >= psShape->nVertices
-                    && psShape->nVertices > 0)
-                || (psShape->panPartStart[i] > 0 && psShape->nVertices == 0) )
+            if (psShape->panPartStart[i] < 0 ||
+                (psShape->panPartStart[i] >= psShape->nVertices &&
+                 psShape->nVertices > 0) ||
+                (psShape->panPartStart[i] > 0 && psShape->nVertices == 0))
             {
+                char szErrorMsg[160];
                 snprintf(szErrorMsg, sizeof(szErrorMsg),
-                         "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
-                         hEntity, i, psShape->panPartStart[i], psShape->nVertices);
-                szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-                psSHP->sHooks.Error( szErrorMsg );
+                         "Corrupted .shp file : shape %d : panPartStart[%d] = "
+                         "%d, nVertices = %d",
+                         hEntity, i, psShape->panPartStart[i],
+                         psShape->nVertices);
+                szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+                psSHP->sHooks.Error(szErrorMsg);
                 SHPDestroyObject(psShape);
                 return SHPLIB_NULLPTR;
             }
-            if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
+            if (i > 0 &&
+                psShape->panPartStart[i] <= psShape->panPartStart[i - 1])
             {
+                char szErrorMsg[160];
                 snprintf(szErrorMsg, sizeof(szErrorMsg),
-                         "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
-                         hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]);
-                szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-                psSHP->sHooks.Error( szErrorMsg );
+                         "Corrupted .shp file : shape %d : panPartStart[%d] = "
+                         "%d, panPartStart[%d] = %d",
+                         hEntity, i, psShape->panPartStart[i], i - 1,
+                         psShape->panPartStart[i - 1]);
+                szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+                psSHP->sHooks.Error(szErrorMsg);
                 SHPDestroyObject(psShape);
                 return SHPLIB_NULLPTR;
             }
         }
 
-        nOffset = 44 + 8 + 4*nParts;
+        int nOffset = 44 + 8 + 4 * nParts;
 
-/* -------------------------------------------------------------------- */
-/*      If this is a multipatch, we will also have parts types.         */
-/* -------------------------------------------------------------------- */
-        if( psShape->nSHPType == SHPT_MULTIPATCH )
+        /* -------------------------------------------------------------------- */
+        /*      If this is a multipatch, we will also have parts types.         */
+        /* -------------------------------------------------------------------- */
+        if (psShape->nSHPType == SHPT_MULTIPATCH)
         {
-            memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
-            for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
+            memcpy(psShape->panPartType, psSHP->pabyRec + nOffset, 4 * nParts);
+            for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
             {
-                if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
+                if (bBigEndian)
+                    SwapWord(4, psShape->panPartType + i);
             }
 
-            nOffset += 4*nParts;
+            nOffset += 4 * nParts;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Copy out the vertices from the record.                          */
-/* -------------------------------------------------------------------- */
-        for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+        /* -------------------------------------------------------------------- */
+        /*      Copy out the vertices from the record.                          */
+        /* -------------------------------------------------------------------- */
+        for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
         {
-            memcpy(psShape->padfX + i,
-                   psSHP->pabyRec + nOffset + i * 16,
-                   8 );
+            memcpy(psShape->padfX + i, psSHP->pabyRec + nOffset + i * 16, 8);
 
-            memcpy(psShape->padfY + i,
-                   psSHP->pabyRec + nOffset + i * 16 + 8,
-                   8 );
+            memcpy(psShape->padfY + i, psSHP->pabyRec + nOffset + i * 16 + 8,
+                   8);
 
-            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
-            if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+            if (bBigEndian)
+                SwapWord(8, psShape->padfX + i);
+            if (bBigEndian)
+                SwapWord(8, psShape->padfY + i);
         }
 
-        nOffset += 16*nPoints;
+        nOffset += 16 * nPoints;
 
-/* -------------------------------------------------------------------- */
-/*      If we have a Z coordinate, collect that now.                    */
-/* -------------------------------------------------------------------- */
-        if( psShape->nSHPType == SHPT_POLYGONZ
-            || psShape->nSHPType == SHPT_ARCZ
-            || psShape->nSHPType == SHPT_MULTIPATCH )
+        /* -------------------------------------------------------------------- */
+        /*      If we have a Z coordinate, collect that now.                    */
+        /* -------------------------------------------------------------------- */
+        if (psShape->nSHPType == SHPT_POLYGONZ ||
+            psShape->nSHPType == SHPT_ARCZ ||
+            psShape->nSHPType == SHPT_MULTIPATCH)
         {
-            memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+            memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8);
+            memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8);
 
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfZMin));
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfZMax));
 
-            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+            for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
             {
-                memcpy( psShape->padfZ + i,
-                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
-                if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+                memcpy(psShape->padfZ + i,
+                       psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+                if (bBigEndian)
+                    SwapWord(8, psShape->padfZ + i);
             }
 
-            nOffset += 16 + 8*nPoints;
+            nOffset += 16 + 8 * nPoints;
         }
-        else if( psShape->bFastModeReadObject )
+        else if (psShape->bFastModeReadObject)
         {
             psShape->padfZ = SHPLIB_NULLPTR;
         }
 
-/* -------------------------------------------------------------------- */
-/*      If we have a M measure value, then read it now.  We assume      */
-/*      that the measure can be present for any shape if the size is    */
-/*      big enough, but really it will only occur for the Z shapes      */
-/*      (options), and the M shapes.                                    */
-/* -------------------------------------------------------------------- */
-        if( nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8*nPoints) )
+        /* -------------------------------------------------------------------- */
+        /*      If we have a M measure value, then read it now.  We assume      */
+        /*      that the measure can be present for any shape if the size is    */
+        /*      big enough, but really it will only occur for the Z shapes      */
+        /*      (options), and the M shapes.                                    */
+        /* -------------------------------------------------------------------- */
+        if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints))
         {
-            memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+            memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8);
+            memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8);
 
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfMMin));
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfMMax));
 
-            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+            for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
             {
-                memcpy( psShape->padfM + i,
-                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
-                if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+                memcpy(psShape->padfM + i,
+                       psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+                if (bBigEndian)
+                    SwapWord(8, psShape->padfM + i);
             }
             psShape->bMeasureIsUsed = TRUE;
         }
-        else if( psShape->bFastModeReadObject )
+        else if (psShape->bFastModeReadObject)
         {
             psShape->padfM = SHPLIB_NULLPTR;
         }
     }
 
-/* ==================================================================== */
-/*  Extract vertices for a MultiPoint.                                 */
-/* ==================================================================== */
-    else if( psShape->nSHPType == SHPT_MULTIPOINT
-             || psShape->nSHPType == SHPT_MULTIPOINTM
-             || psShape->nSHPType == SHPT_MULTIPOINTZ )
+    /* ==================================================================== */
+    /*  Extract vertices for a MultiPoint.                                  */
+    /* ==================================================================== */
+    else if (psShape->nSHPType == SHPT_MULTIPOINT ||
+             psShape->nSHPType == SHPT_MULTIPOINTM ||
+             psShape->nSHPType == SHPT_MULTIPOINTZ)
     {
-        int32          nPoints;
-        int                    i, nOffset;
-        unsigned char* pBuffer = SHPLIB_NULLPTR;
-        unsigned char** ppBuffer = SHPLIB_NULLPTR;
-
-        if ( 44 + 4 > nEntitySize )
+        if (44 + 4 > nEntitySize)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nEntitySize = %d",
                      hEntity, nEntitySize);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
-        memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
+        uint32_t nPoints;
+        memcpy(&nPoints, psSHP->pabyRec + 44, 4);
 
-        if( bBigEndian ) SwapWord( 4, &nPoints );
+        if (bBigEndian)
+            SwapWord(4, &nPoints);
 
         /* nPoints is unsigned */
         if (/* nPoints < 0 || */ nPoints > 50 * 1000 * 1000)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Corrupted .shp file : shape %d : nPoints = %u",
-                     hEntity, nPoints);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+                     "Corrupted .shp file : shape %d : nPoints = %u", hEntity,
+                     nPoints);
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
 
-        nRequiredSize = 48 + nPoints * 16;
-        if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+        int nRequiredSize = 48 + nPoints * 16;
+        if (psShape->nSHPType == SHPT_MULTIPOINTZ)
         {
             nRequiredSize += 16 + nPoints * 8;
         }
         if (nRequiredSize > nEntitySize)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Corrupted .shp file : shape %d : nPoints = %u, nEntitySize = %d",
+                     "Corrupted .shp file : shape %d : nPoints = %u, "
+                     "nEntitySize = %d",
                      hEntity, nPoints, nEntitySize);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
 
-        if( psShape->bFastModeReadObject )
+        unsigned char *pBuffer = SHPLIB_NULLPTR;
+        unsigned char **ppBuffer = SHPLIB_NULLPTR;
+
+        if (psShape->bFastModeReadObject)
         {
-            int nObjectBufSize = 4 * sizeof(double) * nPoints;
+            const int nObjectBufSize = 4 * sizeof(double) * nPoints;
             pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
             ppBuffer = &pBuffer;
         }
 
         psShape->nVertices = nPoints;
 
-        psShape->padfX = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
-        psShape->padfY = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
-        psShape->padfZ = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
-        psShape->padfM = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfX = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfY = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfZ = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+        psShape->padfM = STATIC_CAST(
+            double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
 
         if (psShape->padfX == SHPLIB_NULLPTR ||
             psShape->padfY == SHPLIB_NULLPTR ||
             psShape->padfZ == SHPLIB_NULLPTR ||
             psShape->padfM == SHPLIB_NULLPTR)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
-                     "Probably broken SHP file", nPoints, hEntity );
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+                     "Not enough memory to allocate requested memory "
+                     "(nPoints=%u) for shape %d. "
+                     "Probably broken SHP file",
+                     nPoints, hEntity);
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
 
-        for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+        for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
         {
-            memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
-            memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
+            memcpy(psShape->padfX + i, psSHP->pabyRec + 48 + 16 * i, 8);
+            memcpy(psShape->padfY + i, psSHP->pabyRec + 48 + 16 * i + 8, 8);
 
-            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
-            if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+            if (bBigEndian)
+                SwapWord(8, psShape->padfX + i);
+            if (bBigEndian)
+                SwapWord(8, psShape->padfY + i);
         }
 
-        nOffset = 48 + 16*nPoints;
+        int nOffset = 48 + 16 * nPoints;
 
-/* -------------------------------------------------------------------- */
-/*     Get the X/Y bounds.                                             */
-/* -------------------------------------------------------------------- */
-        memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
-        memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
-        memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
-        memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
+        /* -------------------------------------------------------------------- */
+        /*      Get the X/Y bounds.                                             */
+        /* -------------------------------------------------------------------- */
+        memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8);
+        memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8);
+        memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8);
+        memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8);
 
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
-        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfXMin));
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfYMin));
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfXMax));
+        if (bBigEndian)
+            SwapWord(8, &(psShape->dfYMax));
 
-/* -------------------------------------------------------------------- */
-/*      If we have a Z coordinate, collect that now.                    */
-/* -------------------------------------------------------------------- */
-        if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+        /* -------------------------------------------------------------------- */
+        /*      If we have a Z coordinate, collect that now.                    */
+        /* -------------------------------------------------------------------- */
+        if (psShape->nSHPType == SHPT_MULTIPOINTZ)
         {
-            memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+            memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8);
+            memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8);
 
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfZMin));
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfZMax));
 
-            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+            for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
             {
-                memcpy( psShape->padfZ + i,
-                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
-                if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+                memcpy(psShape->padfZ + i,
+                       psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+                if (bBigEndian)
+                    SwapWord(8, psShape->padfZ + i);
             }
 
-            nOffset += 16 + 8*nPoints;
+            nOffset += 16 + 8 * nPoints;
         }
-        else if( psShape->bFastModeReadObject )
+        else if (psShape->bFastModeReadObject)
             psShape->padfZ = SHPLIB_NULLPTR;
 
-/* -------------------------------------------------------------------- */
-/*      If we have a M measure value, then read it now.  We assume      */
-/*      that the measure can be present for any shape if the size is    */
-/*      big enough, but really it will only occur for the Z shapes      */
-/*      (options), and the M shapes.                                    */
-/* -------------------------------------------------------------------- */
-        if( nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8*nPoints) )
+        /* -------------------------------------------------------------------- */
+        /*      If we have a M measure value, then read it now.  We assume      */
+        /*      that the measure can be present for any shape if the size is    */
+        /*      big enough, but really it will only occur for the Z shapes      */
+        /*      (options), and the M shapes.                                    */
+        /* -------------------------------------------------------------------- */
+        if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints))
         {
-            memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+            memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8);
+            memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8);
 
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfMMin));
+            if (bBigEndian)
+                SwapWord(8, &(psShape->dfMMax));
 
-            for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+            for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
             {
-                memcpy( psShape->padfM + i,
-                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
-                if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+                memcpy(psShape->padfM + i,
+                       psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+                if (bBigEndian)
+                    SwapWord(8, psShape->padfM + i);
             }
             psShape->bMeasureIsUsed = TRUE;
         }
-        else if( psShape->bFastModeReadObject )
+        else if (psShape->bFastModeReadObject)
             psShape->padfM = SHPLIB_NULLPTR;
     }
 
-/* ==================================================================== */
-/*      Extract vertices for a point.                                   */
-/* ==================================================================== */
-    else if( psShape->nSHPType == SHPT_POINT
-             || psShape->nSHPType == SHPT_POINTM
-             || psShape->nSHPType == SHPT_POINTZ )
+    /* ==================================================================== */
+    /*      Extract vertices for a point.                                   */
+    /* ==================================================================== */
+    else if (psShape->nSHPType == SHPT_POINT ||
+             psShape->nSHPType == SHPT_POINTM ||
+             psShape->nSHPType == SHPT_POINTZ)
     {
-        int    nOffset;
-
         psShape->nVertices = 1;
-        if( psShape->bFastModeReadObject )
+        if (psShape->bFastModeReadObject)
         {
             psShape->padfX = &(psShape->dfXMin);
             psShape->padfY = &(psShape->dfYMin);
@@ -2741,123 +2638,126 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
         else
         {
-            psShape->padfX = STATIC_CAST(double *, calloc(1,sizeof(double)));
-            psShape->padfY = STATIC_CAST(double *, calloc(1,sizeof(double)));
-            psShape->padfZ = STATIC_CAST(double *, calloc(1,sizeof(double)));
-            psShape->padfM = STATIC_CAST(double *, calloc(1,sizeof(double)));
+            psShape->padfX = STATIC_CAST(double *, calloc(1, sizeof(double)));
+            psShape->padfY = STATIC_CAST(double *, calloc(1, sizeof(double)));
+            psShape->padfZ = STATIC_CAST(double *, calloc(1, sizeof(double)));
+            psShape->padfM = STATIC_CAST(double *, calloc(1, sizeof(double)));
         }
 
-        if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
+        if (20 + 8 + ((psShape->nSHPType == SHPT_POINTZ) ? 8 : 0) > nEntitySize)
         {
+            char szErrorMsg[160];
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nEntitySize = %d",
                      hEntity, nEntitySize);
-            szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
-            psSHP->sHooks.Error( szErrorMsg );
+            szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+            psSHP->sHooks.Error(szErrorMsg);
             SHPDestroyObject(psShape);
             return SHPLIB_NULLPTR;
         }
-        memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
-        memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
+        memcpy(psShape->padfX, psSHP->pabyRec + 12, 8);
+        memcpy(psShape->padfY, psSHP->pabyRec + 20, 8);
 
-        if( bBigEndian ) SwapWord( 8, psShape->padfX );
-        if( bBigEndian ) SwapWord( 8, psShape->padfY );
+        if (bBigEndian)
+            SwapWord(8, psShape->padfX);
+        if (bBigEndian)
+            SwapWord(8, psShape->padfY);
 
-        nOffset = 20 + 8;
+        int nOffset = 20 + 8;
 
-/* -------------------------------------------------------------------- */
-/*      If we have a Z coordinate, collect that now.                    */
-/* -------------------------------------------------------------------- */
-        if( psShape->nSHPType == SHPT_POINTZ )
+        /* -------------------------------------------------------------------- */
+        /*      If we have a Z coordinate, collect that now.                    */
+        /* -------------------------------------------------------------------- */
+        if (psShape->nSHPType == SHPT_POINTZ)
         {
-            memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
+            memcpy(psShape->padfZ, psSHP->pabyRec + nOffset, 8);
 
-            if( bBigEndian ) SwapWord( 8, psShape->padfZ );
+            if (bBigEndian)
+                SwapWord(8, psShape->padfZ);
 
             nOffset += 8;
         }
 
-/* -------------------------------------------------------------------- */
-/*      If we have a M measure value, then read it now.  We assume      */
-/*      that the measure can be present for any shape if the size is    */
-/*      big enough, but really it will only occur for the Z shapes      */
-/*      (options), and the M shapes.                                    */
-/* -------------------------------------------------------------------- */
-        if( nEntitySize >= nOffset + 8 )
+        /* -------------------------------------------------------------------- */
+        /*      If we have a M measure value, then read it now.  We assume      */
+        /*      that the measure can be present for any shape if the size is    */
+        /*      big enough, but really it will only occur for the Z shapes      */
+        /*      (options), and the M shapes.                                    */
+        /* -------------------------------------------------------------------- */
+        if (nEntitySize >= nOffset + 8)
         {
-            memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
+            memcpy(psShape->padfM, psSHP->pabyRec + nOffset, 8);
 
-            if( bBigEndian ) SwapWord( 8, psShape->padfM );
+            if (bBigEndian)
+                SwapWord(8, psShape->padfM);
             psShape->bMeasureIsUsed = TRUE;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Since no extents are supplied in the record, we will apply      */
-/*      them from the single vertex.                                    */
-/* -------------------------------------------------------------------- */
+        /* -------------------------------------------------------------------- */
+        /*      Since no extents are supplied in the record, we will apply      */
+        /*      them from the single vertex.                                    */
+        /* -------------------------------------------------------------------- */
         psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
         psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
         psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
         psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
     }
 
-    return( psShape );
+    return (psShape);
 }
 
 /************************************************************************/
 /*                            SHPTypeName()                             */
 /************************************************************************/
 
-const char SHPAPI_CALL1(*)
-SHPTypeName( int nSHPType )
-
+const char SHPAPI_CALL1(*) SHPTypeName(int nSHPType)
 {
-    switch( nSHPType )
+    switch (nSHPType)
     {
-      case SHPT_NULL:
-        return "NullShape";
+        case SHPT_NULL:
+            return "NullShape";
 
-      case SHPT_POINT:
-        return "Point";
+        case SHPT_POINT:
+            return "Point";
 
-      case SHPT_ARC:
-        return "Arc";
+        case SHPT_ARC:
+            return "Arc";
 
-      case SHPT_POLYGON:
-        return "Polygon";
+        case SHPT_POLYGON:
+            return "Polygon";
 
-      case SHPT_MULTIPOINT:
-        return "MultiPoint";
+        case SHPT_MULTIPOINT:
+            return "MultiPoint";
 
-      case SHPT_POINTZ:
-        return "PointZ";
+        case SHPT_POINTZ:
+            return "PointZ";
 
-      case SHPT_ARCZ:
-        return "ArcZ";
+        case SHPT_ARCZ:
+            return "ArcZ";
 
-      case SHPT_POLYGONZ:
-        return "PolygonZ";
+        case SHPT_POLYGONZ:
+            return "PolygonZ";
 
-      case SHPT_MULTIPOINTZ:
-        return "MultiPointZ";
+        case SHPT_MULTIPOINTZ:
+            return "MultiPointZ";
 
-      case SHPT_POINTM:
-        return "PointM";
+        case SHPT_POINTM:
+            return "PointM";
 
-      case SHPT_ARCM:
-        return "ArcM";
+        case SHPT_ARCM:
+            return "ArcM";
 
-      case SHPT_POLYGONM:
-        return "PolygonM";
+        case SHPT_POLYGONM:
+            return "PolygonM";
 
-      case SHPT_MULTIPOINTM:
-        return "MultiPointM";
+        case SHPT_MULTIPOINTM:
+            return "MultiPointM";
 
-      case SHPT_MULTIPATCH:
-        return "MultiPatch";
+        case SHPT_MULTIPATCH:
+            return "MultiPatch";
 
-      default:
-        return "UnknownShapeType";
+        default:
+            return "UnknownShapeType";
     }
 }
 
@@ -2865,32 +2765,30 @@ SHPTypeName( int nSHPType )
 /*                          SHPPartTypeName()                           */
 /************************************************************************/
 
-const char SHPAPI_CALL1(*)
-SHPPartTypeName( int nPartType )
-
+const char SHPAPI_CALL1(*) SHPPartTypeName(int nPartType)
 {
-    switch( nPartType )
+    switch (nPartType)
     {
-      case SHPP_TRISTRIP:
-        return "TriangleStrip";
+        case SHPP_TRISTRIP:
+            return "TriangleStrip";
 
-      case SHPP_TRIFAN:
-        return "TriangleFan";
+        case SHPP_TRIFAN:
+            return "TriangleFan";
 
-      case SHPP_OUTERRING:
-        return "OuterRing";
+        case SHPP_OUTERRING:
+            return "OuterRing";
 
-      case SHPP_INNERRING:
-        return "InnerRing";
+        case SHPP_INNERRING:
+            return "InnerRing";
 
-      case SHPP_FIRSTRING:
-        return "FirstRing";
+        case SHPP_FIRSTRING:
+            return "FirstRing";
 
-      case SHPP_RING:
-        return "Ring";
+        case SHPP_RING:
+            return "Ring";
 
-      default:
-        return "UnknownPartType";
+        default:
+            return "UnknownPartType";
     }
 }
 
@@ -2898,118 +2796,130 @@ SHPPartTypeName( int nPartType )
 /*                          SHPDestroyObject()                          */
 /************************************************************************/
 
-void SHPAPI_CALL
-SHPDestroyObject( SHPObject * psShape )
-
+void SHPAPI_CALL SHPDestroyObject(SHPObject *psShape)
 {
-    if( psShape == SHPLIB_NULLPTR )
+    if (psShape == SHPLIB_NULLPTR)
         return;
 
-    if( psShape->bFastModeReadObject )
+    if (psShape->bFastModeReadObject)
     {
         psShape->bFastModeReadObject = FALSE;
         return;
     }
 
-    if( psShape->padfX != SHPLIB_NULLPTR )
-        free( psShape->padfX );
-    if( psShape->padfY != SHPLIB_NULLPTR )
-        free( psShape->padfY );
-    if( psShape->padfZ != SHPLIB_NULLPTR )
-        free( psShape->padfZ );
-    if( psShape->padfM != SHPLIB_NULLPTR )
-        free( psShape->padfM );
+    if (psShape->padfX != SHPLIB_NULLPTR)
+        free(psShape->padfX);
+    if (psShape->padfY != SHPLIB_NULLPTR)
+        free(psShape->padfY);
+    if (psShape->padfZ != SHPLIB_NULLPTR)
+        free(psShape->padfZ);
+    if (psShape->padfM != SHPLIB_NULLPTR)
+        free(psShape->padfM);
 
-    if( psShape->panPartStart != SHPLIB_NULLPTR )
-        free( psShape->panPartStart );
-    if( psShape->panPartType != SHPLIB_NULLPTR )
-        free( psShape->panPartType );
+    if (psShape->panPartStart != SHPLIB_NULLPTR)
+        free(psShape->panPartStart);
+    if (psShape->panPartType != SHPLIB_NULLPTR)
+        free(psShape->panPartType);
 
-    free( psShape );
+    free(psShape);
 }
 
 /************************************************************************/
 /*                       SHPGetPartVertexCount()                        */
 /************************************************************************/
 
-static int SHPGetPartVertexCount( const SHPObject * psObject, int iPart )
+static int SHPGetPartVertexCount(const SHPObject *psObject, int iPart)
 {
-    if( iPart == psObject->nParts-1 )
+    if (iPart == psObject->nParts - 1)
         return psObject->nVertices - psObject->panPartStart[iPart];
     else
-        return psObject->panPartStart[iPart+1] - psObject->panPartStart[iPart];
+        return psObject->panPartStart[iPart + 1] -
+               psObject->panPartStart[iPart];
 }
 
 /************************************************************************/
 /*                      SHPRewindIsInnerRing()                          */
 /************************************************************************/
 
-static int SHPRewindIsInnerRing( const SHPObject * psObject,
-                                 int iOpRing )
+/* Return -1 in case of ambiguity */
+static int SHPRewindIsInnerRing(const SHPObject *psObject, int iOpRing,
+                                double dfTestX, double dfTestY,
+                                double dfRelativeTolerance, int bSameZ,
+                                double dfTestZ)
 {
-/* -------------------------------------------------------------------- */
-/*      Determine if this ring is an inner ring or an outer ring        */
-/*      relative to all the other rings.  For now we assume the         */
-/*      first ring is outer and all others are inner, but eventually    */
-/*      we need to fix this to handle multiple island polygons and      */
-/*      unordered sets of rings.                                        */
-/*                                                                      */
-/* -------------------------------------------------------------------- */
-
-    /* Use point in the middle of segment to avoid testing
-     * common points of rings.
-     */
-    const int iOpRingStart = psObject->panPartStart[iOpRing];
-    double dfTestX = ( psObject->padfX[iOpRingStart] +
-                       psObject->padfX[iOpRingStart + 1] ) / 2;
-    double dfTestY = ( psObject->padfY[iOpRingStart] +
-                       psObject->padfY[iOpRingStart + 1] ) / 2;
-
-    int bInner = FALSE;
-    int iCheckRing;
-    for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
-    {
-        int nVertStartCheck, nVertCountCheck;
-        int iEdge;
-
-        if( iCheckRing == iOpRing )
+    /* -------------------------------------------------------------------- */
+    /*      Determine if this ring is an inner ring or an outer ring        */
+    /*      relative to all the other rings.  For now we assume the         */
+    /*      first ring is outer and all others are inner, but eventually    */
+    /*      we need to fix this to handle multiple island polygons and      */
+    /*      unordered sets of rings.                                        */
+    /*                                                                      */
+    /* -------------------------------------------------------------------- */
+
+    bool bInner = false;
+    for (int iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++)
+    {
+        if (iCheckRing == iOpRing)
             continue;
 
-        nVertStartCheck = psObject->panPartStart[iCheckRing];
-        nVertCountCheck = SHPGetPartVertexCount(psObject, iCheckRing);
+        const int nVertStartCheck = psObject->panPartStart[iCheckRing];
+        const int nVertCountCheck = SHPGetPartVertexCount(psObject, iCheckRing);
 
-        for( iEdge = 0; iEdge < nVertCountCheck; iEdge++ )
+        /* Ignore rings that don't have the same (constant) Z value as the
+         * point. */
+        /* As noted in SHPRewindObject(), this is a simplification */
+        /* of what we should ideally do. */
+        if (!bSameZ)
         {
-            int iNext;
+            int bZTestOK = TRUE;
+            for (int iVert = nVertStartCheck + 1;
+                 iVert < nVertStartCheck + nVertCountCheck; ++iVert)
+            {
+                if (psObject->padfZ[iVert] != dfTestZ)
+                {
+                    bZTestOK = FALSE;
+                    break;
+                }
+            }
+            if (!bZTestOK)
+                continue;
+        }
 
-            if( iEdge < nVertCountCheck-1 )
-                iNext = iEdge+1;
+        for (int iEdge = 0; iEdge < nVertCountCheck; iEdge++)
+        {
+            int iNext;
+            if (iEdge < nVertCountCheck - 1)
+                iNext = iEdge + 1;
             else
                 iNext = 0;
 
+            const double y0 = psObject->padfY[iEdge + nVertStartCheck];
+            const double y1 = psObject->padfY[iNext + nVertStartCheck];
             /* Rule #1:
              * Test whether the edge 'straddles' the horizontal ray from
              * the test point (dfTestY,dfTestY)
              * The rule #1 also excludes edges colinear with the ray.
              */
-            if ( ( psObject->padfY[iEdge+nVertStartCheck] < dfTestY
-                    && dfTestY <= psObject->padfY[iNext+nVertStartCheck] )
-                    || ( psObject->padfY[iNext+nVertStartCheck] < dfTestY
-                        && dfTestY <= psObject->padfY[iEdge+nVertStartCheck] ) )
+            if ((y0 < dfTestY && dfTestY <= y1) ||
+                (y1 < dfTestY && dfTestY <= y0))
             {
                 /* Rule #2:
                  * Test if edge-ray intersection is on the right from the
                  * test point (dfTestY,dfTestY)
                  */
-                double const intersect =
-                    ( psObject->padfX[iEdge+nVertStartCheck]
-                        + ( dfTestY - psObject->padfY[iEdge+nVertStartCheck] )
-                        / ( psObject->padfY[iNext+nVertStartCheck] -
-                            psObject->padfY[iEdge+nVertStartCheck] )
-                        * ( psObject->padfX[iNext+nVertStartCheck] -
-                            psObject->padfX[iEdge+nVertStartCheck] ) );
-
-                if (intersect  < dfTestX)
+                const double x0 = psObject->padfX[iEdge + nVertStartCheck];
+                const double x1 = psObject->padfX[iNext + nVertStartCheck];
+                const double intersect_minus_testX =
+                    (x0 - dfTestX) + (dfTestY - y0) / (y1 - y0) * (x1 - x0);
+
+                if (fabs(intersect_minus_testX) <=
+                    dfRelativeTolerance * fabs(dfTestX))
+                {
+                    /* Potential shared edge, or slightly overlapping polygons
+                     */
+                    return -1;
+                }
+                else if (intersect_minus_testX < 0)
                 {
                     bInner = !bInner;
                 }
@@ -3026,96 +2936,169 @@ static int SHPRewindIsInnerRing( const SHPObject * psObject,
 /*      specification.                                                  */
 /************************************************************************/
 
-int SHPAPI_CALL
-SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
-                 SHPObject * psObject )
+int SHPAPI_CALL SHPRewindObject(CPL_UNUSED SHPHandle hSHP, SHPObject *psObject)
 {
-    int  iOpRing, bAltered = 0;
-
-/* -------------------------------------------------------------------- */
-/*      Do nothing if this is not a polygon object.                     */
-/* -------------------------------------------------------------------- */
-    if( psObject->nSHPType != SHPT_POLYGON
-        && psObject->nSHPType != SHPT_POLYGONZ
-        && psObject->nSHPType != SHPT_POLYGONM )
+    /* -------------------------------------------------------------------- */
+    /*      Do nothing if this is not a polygon object.                     */
+    /* -------------------------------------------------------------------- */
+    if (psObject->nSHPType != SHPT_POLYGON &&
+        psObject->nSHPType != SHPT_POLYGONZ &&
+        psObject->nSHPType != SHPT_POLYGONM)
         return 0;
 
-    if( psObject->nVertices == 0 || psObject->nParts == 0 )
+    if (psObject->nVertices == 0 || psObject->nParts == 0)
         return 0;
 
-/* -------------------------------------------------------------------- */
-/*      Process each of the rings.                                      */
-/* -------------------------------------------------------------------- */
-    for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
+    /* -------------------------------------------------------------------- */
+    /*      Test if all points have the same Z value.                       */
+    /* -------------------------------------------------------------------- */
+    int bSameZ = TRUE;
+    if (psObject->nSHPType == SHPT_POLYGONZ ||
+        psObject->nSHPType == SHPT_POLYGONM)
     {
-        int      bInner, iVert, nVertCount, nVertStart;
-        double   dfSum;
+        for (int iVert = 1; iVert < psObject->nVertices; ++iVert)
+        {
+            if (psObject->padfZ[iVert] != psObject->padfZ[0])
+            {
+                bSameZ = FALSE;
+                break;
+            }
+        }
+    }
 
-        nVertStart = psObject->panPartStart[iOpRing];
-        nVertCount = SHPGetPartVertexCount(psObject, iOpRing);
+    /* -------------------------------------------------------------------- */
+    /*      Process each of the rings.                                      */
+    /* -------------------------------------------------------------------- */
+    int bAltered = 0;
+    for (int iOpRing = 0; iOpRing < psObject->nParts; iOpRing++)
+    {
+        const int nVertStart = psObject->panPartStart[iOpRing];
+        const int nVertCount = SHPGetPartVertexCount(psObject, iOpRing);
 
         if (nVertCount < 2)
             continue;
 
-        bInner = SHPRewindIsInnerRing(psObject, iOpRing);
-
-/* -------------------------------------------------------------------- */
-/*      Determine the current order of this ring so we will know if     */
-/*      it has to be reversed.                                          */
-/* -------------------------------------------------------------------- */
+        /* If a ring has a non-constant Z value, then consider it as an outer */
+        /* ring. */
+        /* NOTE: this is a rough approximation. If we were smarter, */
+        /* we would check that all points of the ring are coplanar, and compare
+         */
+        /* that to other rings in the same (oblique) plane. */
+        int bDoIsInnerRingTest = TRUE;
+        if (!bSameZ)
+        {
+            int bPartSameZ = TRUE;
+            for (int iVert = nVertStart + 1; iVert < nVertStart + nVertCount;
+                 ++iVert)
+            {
+                if (psObject->padfZ[iVert] != psObject->padfZ[nVertStart])
+                {
+                    bPartSameZ = FALSE;
+                    break;
+                }
+            }
+            if (!bPartSameZ)
+                bDoIsInnerRingTest = FALSE;
+        }
 
-        dfSum = psObject->padfX[nVertStart] *
-                        (psObject->padfY[nVertStart+1] -
-                         psObject->padfY[nVertStart+nVertCount-1]);
-        for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
+        int bInner = FALSE;
+        if (bDoIsInnerRingTest)
         {
-            dfSum += psObject->padfX[iVert] * (psObject->padfY[iVert+1] -
-                                               psObject->padfY[iVert-1]);
+            for (int iTolerance = 0; iTolerance < 2; iTolerance++)
+            {
+                /* In a first attempt, use a relaxed criterion to decide if a
+                 * point */
+                /* is inside another ring. If all points of the current ring are
+                 * in the */
+                /* "grey" zone w.r.t that criterion, which seems really
+                 * unlikely, */
+                /* then use the strict criterion for another pass. */
+                const double dfRelativeTolerance = (iTolerance == 0) ? 1e-9 : 0;
+                for (int iVert = nVertStart;
+                     iVert + 1 < nVertStart + nVertCount; ++iVert)
+                {
+                    /* Use point in the middle of segment to avoid testing
+                     * common points of rings.
+                     */
+                    const double dfTestX =
+                        (psObject->padfX[iVert] + psObject->padfX[iVert + 1]) /
+                        2;
+                    const double dfTestY =
+                        (psObject->padfY[iVert] + psObject->padfY[iVert + 1]) /
+                        2;
+                    const double dfTestZ =
+                        !bSameZ ? psObject->padfZ[nVertStart] : 0;
+
+                    bInner = SHPRewindIsInnerRing(psObject, iOpRing, dfTestX,
+                                                  dfTestY, dfRelativeTolerance,
+                                                  bSameZ, dfTestZ);
+                    if (bInner >= 0)
+                        break;
+                }
+                if (bInner >= 0)
+                    break;
+            }
+            if (bInner < 0)
+            {
+                /* Completely degenerate case. Do not bother touching order. */
+                continue;
+            }
         }
 
-        dfSum += psObject->padfX[iVert] * (psObject->padfY[nVertStart] -
-                                           psObject->padfY[iVert-1]);
+        /* -------------------------------------------------------------------- */
+        /*      Determine the current order of this ring so we will know if     */
+        /*      it has to be reversed.                                          */
+        /* -------------------------------------------------------------------- */
 
-/* -------------------------------------------------------------------- */
-/*      Reverse if necessary.                                           */
-/* -------------------------------------------------------------------- */
-        if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
+        double dfSum = psObject->padfX[nVertStart] *
+                       (psObject->padfY[nVertStart + 1] -
+                        psObject->padfY[nVertStart + nVertCount - 1]);
+        int iVert = nVertStart + 1;
+        for (; iVert < nVertStart + nVertCount - 1; iVert++)
         {
-            int   i;
+            dfSum += psObject->padfX[iVert] *
+                     (psObject->padfY[iVert + 1] - psObject->padfY[iVert - 1]);
+        }
 
+        dfSum += psObject->padfX[iVert] *
+                 (psObject->padfY[nVertStart] - psObject->padfY[iVert - 1]);
+
+        /* -------------------------------------------------------------------- */
+        /*      Reverse if necessary.                                           */
+        /* -------------------------------------------------------------------- */
+        if ((dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner))
+        {
             bAltered++;
-            for( i = 0; i < nVertCount/2; i++ )
+            for (int i = 0; i < nVertCount / 2; i++)
             {
-                double dfSaved;
-
                 /* Swap X */
-                dfSaved = psObject->padfX[nVertStart+i];
-                psObject->padfX[nVertStart+i] =
-                    psObject->padfX[nVertStart+nVertCount-i-1];
-                psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
+                double dfSaved = psObject->padfX[nVertStart + i];
+                psObject->padfX[nVertStart + i] =
+                    psObject->padfX[nVertStart + nVertCount - i - 1];
+                psObject->padfX[nVertStart + nVertCount - i - 1] = dfSaved;
 
                 /* Swap Y */
-                dfSaved = psObject->padfY[nVertStart+i];
-                psObject->padfY[nVertStart+i] =
-                    psObject->padfY[nVertStart+nVertCount-i-1];
-                psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
+                dfSaved = psObject->padfY[nVertStart + i];
+                psObject->padfY[nVertStart + i] =
+                    psObject->padfY[nVertStart + nVertCount - i - 1];
+                psObject->padfY[nVertStart + nVertCount - i - 1] = dfSaved;
 
                 /* Swap Z */
-                if( psObject->padfZ )
+                if (psObject->padfZ)
                 {
-                    dfSaved = psObject->padfZ[nVertStart+i];
-                    psObject->padfZ[nVertStart+i] =
-                        psObject->padfZ[nVertStart+nVertCount-i-1];
-                    psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
+                    dfSaved = psObject->padfZ[nVertStart + i];
+                    psObject->padfZ[nVertStart + i] =
+                        psObject->padfZ[nVertStart + nVertCount - i - 1];
+                    psObject->padfZ[nVertStart + nVertCount - i - 1] = dfSaved;
                 }
 
                 /* Swap M */
-                if( psObject->padfM )
+                if (psObject->padfM)
                 {
-                    dfSaved = psObject->padfM[nVertStart+i];
-                    psObject->padfM[nVertStart+i] =
-                        psObject->padfM[nVertStart+nVertCount-i-1];
-                    psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
+                    dfSaved = psObject->padfM[nVertStart + i];
+                    psObject->padfM[nVertStart + i] =
+                        psObject->padfM[nVertStart + nVertCount - i - 1];
+                    psObject->padfM[nVertStart + nVertCount - i - 1] = dfSaved;
                 }
             }
         }